Clang/LLVM + X11 (Вопрос: как собрать приложение для X11?)

Модератор: Модераторы разделов

Аватара пользователя
bigov
Сообщения: 10
ОС: Arch Linux + Xfce4

Clang/LLVM + X11

Сообщение bigov »

Привет всем, кто имеет опыт работы с Clang - прошу поделиться знаниями.

Не могу найти информацию, как clang-ом собрать бинарный файл для X11, чтобы он определялся не как "Разделяемая библиотека", а как "Исполняемый". То есть, чтобы приложение можно было "открыть" двойным кликом мышки в GIU файловом менеджере (Thunar, Nautilus и т.п.).

Для справки: как собрать бинарник под X11, определяемый файловым менеджером как "Исполняемый " при помощи GCC описано (ключ -no-pie) тут: Сборка GUI приложения в GCC для X-desktop. Но Clang так собирать отказывается: ключик "-fno-PIE" не работает.

Для тестирования я использую простое приложение с библиотекой gtkmm, которое создает одно GUI окошко:
Spoiler

Код: Выделить всё

#include <gtkmm.h>

class app_win: public Gtk::Window
{
  public:
    app_win();
    virtual ~app_win() {}

  protected:
    Gtk::Box m_box { Gtk::ORIENTATION_VERTICAL };
    Gtk::Label label { "Выход: <Esc>" };

  private:
    bool on_key_press_event (GdkEventKey* event) override;
};

app_win::app_win()
{
  set_border_width(40);
  add(m_box);
  m_box.add(label);
  show_all_children();
}

/// Обработчик нажатий клавиатуры
bool app_win::on_key_press_event(GdkEventKey* event)
{
  if(event->keyval == GDK_KEY_Escape)
  {
    hide();
    return true;
  }
  return Gtk::Window::on_key_press_event(event);
}

int main(int argc, char* argv[])
{
  auto app = Gtk::Application::create(argc, argv, "");
  app_win window {};
  return app->run(window);
}
Для сборки используется cmake файл:
Spoiler

Код: Выделить всё

# По-умолчанию используется GCC
#
# Если надо Clang, то запускаем так:
#   CC="clang" CXX="clang++" cmake ../ && cmake --build .

cmake_minimum_required( VERSION 3.15 )
project( SimpleTests )
SET( PROJECT_AUTHOR "bigov" )
SET( PROJECT_AUTHOR_EMAIL "bigov@yandex.ru" )
SET( APP "simple" )

if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
  message(FATAL_ERROR "Prevented in-tree built. Please create a build \
  directory outside of the source code and call cmake from there. Thank you.")
endif()

if( NOT CMAKE_BUILD_TYPE )
    SET( CMAKE_BUILD_TYPE Debug )
endif()

SET( SKIP_INSTALL_ALL ON CACHE BOOL "" FORCE ) # Ничего не устанавливать

SET( CMAKE_CXX_STANDARD "20")
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64 -std=c++2a -Werror -Wall -Wextra \
  -Wpedantic -Woverloaded-virtual -Winit-self -Wunreachable-code" )
# -Wconversion -Wold-style-cast -Wctor-dtor-privacy -Wnon-virtual-dtor -Weffc++" )
SET( CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE )

if( "_$ENV{CC}" MATCHES "clang" )
  SET( CMAKE_C_COMPILER clang )
  SET( CMAKE_CXX_COMPILER clang++ )
  #SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-PIE" )
  SET( SUFFIX "clang" )
else( "_$ENV{CC}" MATCHES "clang" )
  SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-pie" )
  SET( SUFFIX "gcc" )
endif( "_$ENV{CC}" MATCHES "clang" )
SET( APP "${APP}_${SUFFIX}" )

if( ${CMAKE_SYSTEM_NAME} MATCHES "Windows" )
  SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows -Wl,-subsystem,windows" )
endif()

find_package( PkgConfig REQUIRED )
pkg_check_modules( GTKMM REQUIRED gtkmm-3.0 )
link_directories( ${GTKMM_LIBRARY_DIRS} )
include_directories( ${GTKMM_INCLUDE_DIRS} )

add_executable( ${APP} "main.cpp" )
target_link_libraries( ${APP} ${GTKMM_LIBRARIES} )
Можно посмотреть исходные файлы на Гитхабе: https://github.com/bigov/daft-lib/tree/master/gui_samples/gtkmm.

Чтобы уменьшить число "пустых советов", предлагаю считать:
  1. используемая графическая библиотека не влияет на результат,
  2. операционная система и версия ядра не влияет на результат (ps: как позже оказалось - не везде одинаково),
  3. бинарник создается всегда с атрибутами "исполняемый" и стартует из терминальной строки, но ФМ определяет по-своему,
  4. создание ярлыка ".desktop" решает проблему, но это не ответ на вопрос, а обход проблемы - "костыль", а ищется "решение".


Исходники:
main.cpp
CMakeLists.txt
--- --- ---

РЕШЕНИЕ:

Shell

--- CMakeLists.txt
+++ CMakeLists.txt
@@ -26,14 +26,13 @@ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64 -std=c++2a -Werror -Wall -Wextra \
-Wpedantic -Woverloaded-virtual -Winit-self -Wunreachable-code" )
# -Wconversion -Wold-style-cast -Wctor-dtor-privacy -Wnon-virtual-dtor -Weffc++" )
SET( CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE )
+SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie" )

if( "_$ENV{CC}" MATCHES "clang" )
SET( CMAKE_C_COMPILER clang )
SET( CMAKE_CXX_COMPILER clang++ )
- #SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-PIE" )
SET( SUFFIX "clang" )
else( "_$ENV{CC}" MATCHES "clang" )
- SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-pie" )
SET( SUFFIX "gcc" )
endif( "_$ENV{CC}" MATCHES "clang" )
SET( APP "${APP}_${SUFFIX}" )
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось bigov 23.01.2020 15:06, всего редактировалось 4 раза.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

Во-первых, вам уже говорили, что нет такого понятия, как "исполняемый файл X11". У вас получился нормальный исполняемый файл. То, что Thunar отказывается запускать его двойным кликом, - это баг Thunar и только Thunar. Конкретного файлового менеджера, одного из многих. X11 здесь вообще ни при чём.

Во-вторых, костыль тут - отключение PIE. Оно мешает полноценно использовать ASLR, снижая защищённость вашей программы от эксплойтов. Если она будет работать с сетью или файлами, пришедшими от других людей, отключать PIE не стоит. То, что Thunar не умеет запускать программы, скомпилированные с PIE, двойным кликом, - это, как я уже сказал, проблема Thunar. Не-костыльных решений здесь только 2: либо исправлять баг в Thunar, либо не использовать Thunar. Всё остальное - костыли, и создание .desktop-файла ничуть не костыльнее компиляции без PIE.

В-третьих:
bigov писал(а):
23.01.2020 08:09
Для справки: как собрать "исполняемый для X11" при помощи GCC описано (ключ -no-pie) тут: Сборка GUI приложения в GCC для X-desktop. Но Clang так собирать отказывается: ключик "-fno-PIE" не работает.
Так -no-pie или -fno-PIE? Последний в clang не работает, первый - работает. Кроме чистой компиляции, без линковки.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 18294
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Clang/LLVM + X11

Сообщение Bizdelnick »

/dev/random писал:
23.01.2020 09:56
То, что Thunar отказывается запускать его двойным кликом, - это баг Thunar и только Thunar.
Вообще-то это преподносится как фича, и не только Thunar, но и тем же Nautilus, и многими другими графическими ФМ. В некоторых, вроде бы, настраивается. И PIE тут ни при чём, они со всеми исполнемыми файлами себя так ведут.
bigov писал(а):
23.01.2020 08:09
создание ярлыка ".desktop" решает проблему, но это - "костыль".
Ну вот так почему-то решили, что это должен быть единственный штатный способ запуска приложений в графике.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

Bizdelnick писал:
23.01.2020 10:22
Вообще-то это преподносится как фича, и не только Thunar, но и тем же Nautilus, и многими другими графическими ФМ. В некоторых, вроде бы, настраивается. И PIE тут ни при чём, они со всеми исполнемыми файлами себя так ведут.
Речь вот об этом баге: https://bugzilla.xfce.org/show_bug.cgi?id=13737
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 18294
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Clang/LLVM + X11

Сообщение Bizdelnick »

Интересно, а скрипты он тоже из-за бага не запускает?
Ну, во всяком случае, в Nautilus это точно сделано осознанно.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
bigov
Сообщения: 10
ОС: Arch Linux + Xfce4

Re: Clang/LLVM + X11

Сообщение bigov »

/dev/random писал:
23.01.2020 09:56
Во-первых, вам уже говорили, что нет такого понятия, как "исполняемый файл X11".
Во-первых, о "понятиях" - не надо учить. Я использовал совершенно конкретный термин, применяемый в графической оболочке. Смотрите рисунок:
properties.png
/dev/random писал:
23.01.2020 09:56
Так -no-pie или -fno-PIE? Последний в clang не работает, первый - работает.
Во вторых, Вы уж самостоятельно почитайте про ключи запуска Clang.

В третьих, если не знаете ответа на вопрос, то зачем пишете?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:

Аватара пользователя
bigov
Сообщения: 10
ОС: Arch Linux + Xfce4

Re: Clang/LLVM + X11

Сообщение bigov »

Bizdelnick писал:
23.01.2020 10:22
Ну вот так почему-то решили, что это должен быть единственный штатный способ запуска приложений в графике.
Не обязательно. Например, игровой движок "godot", собранный из исходников с использованием clang, определяется и Тунаром и Наутилусом как "исполняемый" и прекрасно стартует без ярлыка - кликом мышкой по бинарнику. К сожалению, в нем используется не cmake, а незнакомая для меня система сборки, поэтому КАК ИМЕННО он собирается мне пока не понятно.
Последний раз редактировалось bigov 23.01.2020 14:31, всего редактировалось 1 раз.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

bigov писал(а):
23.01.2020 12:08
Во-первых, о "понятиях" - не надо учить. Я использовал совершенно конкретный термин, применяемый в графической оболочке.
Там нет слова "X11".
bigov писал(а):
23.01.2020 12:08
Во вторых, Вы уж самостоятельно почитайте про ключи запуска Clang.
В clang далеко не все ключи документированы.

Shell

$ echo 'int main() { return 0; }' > tmp.c
$ clang tmp.c
$ file a.out
a.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
$ clang -no-pie tmp.c
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
Нормально собралось, в одном случае с pie, в другом - без.
bigov писал(а):
23.01.2020 12:08
В третьих, если не знаете ответа на вопрос, то зачем пишете?
Я знаю ответ, и я вам его дал.
Спасибо сказали:

Аватара пользователя
bigov
Сообщения: 10
ОС: Arch Linux + Xfce4

Re: Clang/LLVM + X11

Сообщение bigov »

Вобще-то в кланге "-fno-PIE". Ну да, даже так все компилируется:

Код: Выделить всё

$ clang++ -fno-PIE -Werror -Wall -Wextra -Wpedantic -Woverloaded-virtual -Winit-self -Wunreachable-code tmp.cpp 
А при сборке с библиотекой вываливает ошибку:

Код: Выделить всё

[100%] Linking CXX executable simple_clang
/usr/bin/ld: CMakeFiles/simple_clang.dir/main.cpp.o: перемещение R_X86_64_32 для «.rodata.str1.1» не может использоваться при создании объект PIE; recompile with -fPIE
/usr/bin/ld: ошибка конечной ссылки: раздел, непредставимый для вывода
clang-9: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [CMakeFiles/simple_clang.dir/build.make:84: simple_clang] Ошибка 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/simple_clang.dir/all] Ошибка 2
make: *** [Makefile:84: all] Ошибка 2
Не пойму, почему. Может дело в компоновщике?
Добавлено (12:38):
Ожидалось, что кланг ругнется на ключ "-no-pie", а он не стал. УПС... :)
Добавлено (12:51):
/dev/random писал:
23.01.2020 09:56
костыль тут - отключение PIE. Оно мешает полноценно использовать ASLR, снижая защищённость
Это понятно, но вопрос в топике не в том, использовать ASLR или нет. Вопрос был как собрать клангом, чтобы бинарник определился как "Исполняемый". Наверно, надо "покурить" на тему: "по какому признаку файловые менеджеры опреляют тип файла?".
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 18294
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Clang/LLVM + X11

Сообщение Bizdelnick »

bigov писал(а):
23.01.2020 12:23
Не пойму, почему. Может дело в компоновщике?
Нет, дело в неправильных опциях.
Традиционные опции для компиляции: -fPIC, -fPIE. По умолчанию скомпилированный без какой-то из них код мог линковаться только в обычный исполняемый файл (не PIE). Опции для линковки: -shared, -pie, по умолчанию — обычный исполняемый файл.
Современный подход состоит в сборке PIE по умолчанию (как если бы использовались опции -fPIE для компиляции и -pie для линковки), а для компиляции и линковки неперемещаемых исполняемых файлов появились опции -fno-PIE и -no-pie.
Обычный исполняемый файл можно скомпоновать из объектов, скомпилированных в любом режиме, PIE — только в режимах PIE или PIC, разделяемую библиотеку — только PIC. Ваша ошибка в том, что Вы не указали линковщику, что надо скомпоновать неперемещаемый исполняемый файл, а сделать PIE из объектников, скомпилированных с -fno-PIE, он не может.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

bigov писал(а):
23.01.2020 12:23
Это понятно, но вопрос в топике не в том, использовать ASLR или нет. Вопрос был как собрать клангом, чтобы бинарник определился как "Исполняемый". Наверно, надо "покурить" на тему: "по какому признаку файловые менеджеры опреляют тип файла?".
Да по этому и определяют. При сборке исполнимые файлы без PIE помечаются как не-разделяемые с интерпретатором, исполнимые с PIE - как разделяемые с интерпретатором, а библиотеки - как разделяемые без интерпретатора. Т.е. смотреть нужно на то, есть ли интерпретатор, но Thunar вместо этого смотрит на то, разделяемый ли он. Что является багом.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 18294
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Clang/LLVM + X11

Сообщение Bizdelnick »

А в CMakeLists.txt у Вас следующая ошибка: -no-pie надо добавлять в CMAKE_EXE_LINKER_FLAGS, а не CMAKE_CXX_FLAGS. Если Вы таки действительно считаете, что оно Вам надо, хотя на самом деле не надо совершенно.
Добавлено (13:15):
/dev/random писал:
23.01.2020 13:11
Т.е. смотреть нужно на то, есть ли интерпретатор, но Thunar вместо этого смотрит на то, разделяемый ли он.
Да он, как я понимаю, не сам смотрит, а использует libmagic (а то и file вызывает).
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
bigov
Сообщения: 10
ОС: Arch Linux + Xfce4

Re: Clang/LLVM + X11

Сообщение bigov »

Bizdelnick писал:
23.01.2020 13:08
ошибка в том, что Вы не указали линковщику, что надо скомпоновать неперемещаемый исполняемый файл
Спасибо за пояснение. Можете привести корректный, с этой точки зрения, код для моего CMakeLists.txt ?

ps. Уже не надо, все получилось

Код: Выделить всё

...
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie" )
if( "_$ENV{CC}" MATCHES "clang" )
  SET( CMAKE_C_COMPILER clang )
  SET( CMAKE_CXX_COMPILER clang++ )
  SET( SUFFIX "clang" )
else( "_$ENV{CC}" MATCHES "clang" )
  SET( SUFFIX "gcc" )
endif( "_$ENV{CC}" MATCHES "clang" )
SET( APP "${APP}_${SUFFIX}" )
...
Последний раз редактировалось bigov 23.01.2020 13:35, всего редактировалось 1 раз.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

bigov писал(а):
23.01.2020 13:22
Спасибо за пояснение. Можете привести корректный, с этой точки зрения, код для моего CMakeLists.txt ?
Замените вашу закомментированную строку с -fno-PIE на: SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie" )

Хотя если не включать -Werror, то и CMAKE_CXX_FLAGS будет работать, главное -no-pie использовать, а не -fno-PIE. Ваше предупреждение-ставшее-ошибкой означало, что опция -no-pie не используется при компиляции, только при линковке, а CMAKE_CXX_FLAGS передаются и туда, и туда.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 18294
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Clang/LLVM + X11

Сообщение Bizdelnick »

/dev/random писал:
23.01.2020 13:34
Хотя если не включать -Werror, то и CMAKE_CXX_FLAGS будет работать, главное -no-pie использовать, а не -fno-PIE.
Ага, до тех пор, пока не возникнет необходимость рядом ещё и какую-нибудь библиотеку собрать.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 1664
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение ormorph »

Хм, странно а у меня собралось норм с -fno-PIE видюшка. Тот самый CMakeLists.txt использовал, просто раскомментировал.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

ormorph писал(а):
23.01.2020 14:08
Тот самый CMakeLists.txt использовал, просто раскомментировал.
Включаю телепатию: у вас в clang pie выключен по умолчанию? Если у вас соберётся и без раскомментирования, то я прав.
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 1664
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение ormorph »

/dev/random писал:
23.01.2020 14:12
Включаю телепатию: у вас в clang pie выключен по умолчанию? Если у вас соберётся и без раскомментирования, то я прав.
Похоже на то, это можно как нибудь узнать?
В выводе:

Shell

$ clang -### /usr/include/stdlib.h
pie отсутствует.
Собирается и без раскомментирования.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

ormorph писал(а):
23.01.2020 14:28
Похоже на то, это можно как нибудь узнать?
Например, собрать какой-нибудь hello world и посмотреть с помощью file, собралось ли с pie или без.
Спасибо сказали:

Аватара пользователя
bigov
Сообщения: 10
ОС: Arch Linux + Xfce4

Re: Clang/LLVM + X11

Сообщение bigov »

/dev/random писал:
23.01.2020 10:30
Речь вот об этом баге: https://bugzilla.xfce.org/show_bug.cgi?id=13737
Там про Арчик, я в нем и работаю. А (у вас?) в Генте так-же?
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 1664
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение ormorph »

/dev/random писал:
23.01.2020 14:31
Например, собрать какой-нибудь hello world и посмотреть с помощью file, собралось ли с pie или без.
Ну да file - pie не показывает.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 5098
ОС: Gentoo

Re: Clang/LLVM + X11

Сообщение /dev/random »

bigov писал(а):
23.01.2020 14:36
Там про Арчик, я в нем и работаю. А (у вас?) в Генте так-же?
В gentoo куча профилей, и раньше они в этом плане различались. Разработчики планировали это дело унифицировать, но я не знаю, закончили или нет. В моём профиле (возможно, и в остальных): в gcc - да, в clang - нет. Когда я тестировал работу ваших команд в clang, я это делал не на своей основной системе.
Спасибо сказали: