LINUX.ORG.RU

CMake find_package(Threads) падает

 ,


0

1

В общем, решил использовать для своего проекта CMake. В проекте использую SDL2 и SDL2_image (там еще подтянется SDL2_mixer), начал гуглить, как все это слинковать. Сначала я удивился, что CMake из коробки не может подтянуть SDL2-библиотеки, только SDL, потом нашел репозиторий с FindSDL2*.cmake. Окей, склонировал все в корень проекта в cmake/sdl2/. Написал вот такой CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)

project(prototype)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)

add_executable(${PROJECT_NAME} main.c)

target_include_directories(${PROJECT_NAME} PRIVATE graphics)

find_package(SDL2 REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main)

find_package(SDL2_image REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Image)

Валится с:

> cmake -S . -B build
CMake Error at cmake/sdl2/FindSDL2.cmake:243 (message):
  Could NOT find Threads (Threads is required by SDL2).
Call Stack (most recent call first):
  CMakeLists.txt:11 (find_package)


-- Configuring incomplete, errors occurred!

На вот этом if:

...
if(NOT APPLE)
  find_package(Threads QUIET)
  if(NOT Threads_FOUND)
    set(SDL2_THREADS_NOT_FOUND "Could NOT find Threads (Threads is required by SDL2).")
    if(SDL2_FIND_REQUIRED)
      message(FATAL_ERROR ${SDL2_THREADS_NOT_FOUND})
    else()
        if(NOT SDL2_FIND_QUIETLY)
          message(STATUS ${SDL2_THREADS_NOT_FOUND})
        endif()
      return()
    endif()
    unset(SDL2_THREADS_NOT_FOUND)
  endif()
endif()
...

Как я понял, он не может найти pthread. Решил, добавить add_compile_options(-lpthread) также валится.
Заметил, что find /lib -name "*pthread" ничего не выводит, но тестовая сборка с gcc main.c -pthread отрабатывает нормально.
Также я пробовал добавлять set(THREADS_PREFER_PTHREAD_FLAG TRUE) и в мой CMakeLists.txt и в cmake/sdl2/FindSDL2.cmake, но оно тоже не помогало

Почему cmake не может собрать проект? Что я делаю не так?

Решение

Заменить find_package на find_library таким образом:

- find_package(SDL2 REQUIRED)
- target_link_libraries(${PROJECT_NAME} SDL2::Main)
+ find_library(SDL2_LIBRARY NAMES SDL2)
+ target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARY})

- find_package(SDL2_image REQUIRED)
- target_link_libraries(${PROJECT_NAME} SDL2::Image)
+ find_library(SDL2_IMAGE_LIBRARY NAMES SDL2_image)
+ target_link_libraries(${PROJECT_NAME} ${SDL2_IMAGE_LIBRARY})

А если поменять CMakeLists.txt на:

cmake_minimum_required(VERSION 3.10)

project(prototype)
+ find_package(Threads REQUIRED)
- list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)

add_executable(${PROJECT_NAME} main.c)

target_include_directories(${PROJECT_NAME} PRIVATE graphics)

То валится уже на:

> cmake -S . -B build
CMake Error at /usr/share/cmake-3.20/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
  /usr/share/cmake-3.20/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  /usr/share/cmake-3.20/Modules/FindThreads.cmake:238 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:6 (find_package)


-- Configuring incomplete, errors occurred!
snake266 ★★ ()

Сначала я удивился, что CMake из коробки не может подтянуть SDL2-библиотеки, только SDL

Там же CMake модуль идёт вместе с SDL, у меня подтягивает

$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(prototype)

find_package(SDL2 REQUIRED)

add_executable(foo 1.cc)
target_link_libraries(foo PUBLIC ${SDL2_LIBRARIES})
target_include_directories(foo PUBLIC ${SDL2_INCLUDE_DIRS})
$ make VERBOSE=1
...
/usr/bin/c++ CMakeFiles/foo.dir/1.cc.o -o foo  -L/usr/local/lib -Wl,-rpath,/usr/local/lib -Wl,--enable-new-dtags -lSDL2
kvpfs ()
Ответ на: комментарий от u-235

GCC 11-ой версии. Даже с выставленными стандартами падает:

cmake_minimum_required(VERSION 3.10)

project(prototype)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 11)
find_package(Threads REQUIRED)

add_executable(${PROJECT_NAME} main.c)

target_include_directories(${PROJECT_NAME} PRIVATE graphics)
> cmake -S . -B build
CMake Error at /usr/share/cmake-3.20/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
  /usr/share/cmake-3.20/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  /usr/share/cmake-3.20/Modules/FindThreads.cmake:238 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:7 (find_package)
snake266 ★★ ()
Ответ на: комментарий от kvpfs

Удалил FindSDL2.cmake, который брал отсюда, теперь оно использует системный модуль, но все ломается (хотя оно и так было сломано):

> cmake -S . -B build
-- Configuring done
CMake Error at CMakeLists.txt:10 (add_executable):
  Target "prototype" links to target "SDL2::Core" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?
     1	cmake_minimum_required(VERSION 3.10)
     2	
     3	project(prototype)
     4	
     5	set(CMAKE_CXX_STANDARD 11)
     6	set(CMAKE_C_STANDARD 11)
     7	
     8	list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
     9	
    10	add_executable(${PROJECT_NAME} main.c)
    11	
    12	target_include_directories(${PROJECT_NAME} PRIVATE graphics)
    13	
    14	find_package(SDL2 REQUIRED)
    15	target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})
    16	
    17	find_package(SDL2_image REQUIRED)
    18	target_link_libraries(${PROJECT_NAME} SDL2::Image)

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

Модуль, который идёт вместе с SDL2, не экспортирует целей (SDL2::Core). Ну и да, cmake модуль прилагается только к SDL, всякие SDL_image идут без него. Видимо SDL_image надо искать либо через find_library(), либо через pkg-config

kvpfs ()

Используй vcpkg, кроме избавления от мучений, он тебе еще даст возможность статично собрать приложение на всех платформах.

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

Всегда интересовало

А почему cmake не вызывает компилятор напрямую? В чем смысл промежуточного представления, это ведь даже сложнее? Ну пусть так сложилось и т.п., но скоро модули, а это компиляция с зависимостями, т.е. там, наверное, нужно пол cmake’а переписать. Можно было начать всё занаво, правильно, но всё повторяется - там есть какая-то тестовая версия умеющая модули с ninja по середине.

kvpfs ()
Ответ на: Всегда интересовало от kvpfs

Все он вызывает. CMake генератор над другими сложными системами сборок.

https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html CMake -> Unix Makefiles -> gcc

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

CMake -> Unix Makefiles -> gcc

В чём необходимость наличия в этой схеме Unix Makefiles? Ни капли не проще генерить правила для сотни систем со своими «тараканами», чем дергать какую-то абстракцию «компилятор» и передавать ей абстрактные флаги. Это очевидно чисто из архитектурных соображений.

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

Нужно это как минимум для переносимости (насколько это возможно). Например, я написал CMakeLists.txt на линуксе и у меня cmake транслирует инструкции в make, кто-то другой, к примеру на винде, где make без танцев не заводится, транслирует в скрипт сборки, специфичный для винды, или в тот же ninja.

Кстати, кто знает, что там на винде, в том же MS VS используется? Знаю что оно в CMake умеет, но во что оно транслируется?

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

Кстати, кто знает, что там на винде, в том же MS VS используется?

nmake

u-235 ()
Ответ на: комментарий от bhfq

Это какая-то чудовищно неадекватная оценка сложности синтаксиса make и интерфейса ГЦЦ, усложнение на пустом месте.

Причина совсем иная, скорее всего хотелось также клепать проекты для всяких IDE’ек, ну и по такому шаблону всё запилили. По-хорошему надо переделывать, а если идешкам надо, то пусть сами учатся CMakeList.txt парсить.

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

Ага, т.е. возможность напрямую вызвать компилятор в голову не приходит (msvc или гцц), ясно.

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

Пока решил пробовать find_library(), это, мне кажется, более кроссплатформенно, а именно ради этого я и стал мучиться с CMake.

Вот так, он нашел все нужные библиотеки:

cmake_minimum_required(VERSION 3.10)

project(prototype)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 11)

set(SOURCES ... )

add_executable(${PROJECT_NAME} ${SOURCES})

find_library(SDL2_LIBRARY NAMES SDL2)
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARY})

find_library(SDL2_IMAGE_LIBRARY NAMES SDL2_image)
target_link_libraries(${PROJECT_NAME} ${SDL2_IMAGE_LIBRARY})

И проект даже собрался и запустился.

Осталось только найти как красиво подтянуть хедеры с сурсами из папки graphics, а то перечислять все в sources не очень удобно.

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

Только я бы саму базовую SDL искал бы через find_package(), впроде этого:

find_package(SDL2 REQUIRED)

add_executable(foo 1.cc)
target_link_libraries(foo PUBLIC ${SDL2_LIBRARIES})
target_include_directories(foo PUBLIC ${SDL2_INCLUDE_DIRS})

Чтобы подтягивать и инклюд директорию. А потому уже добавлять линкеру SDL_… через find_library().

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

Вообще сейчас «правильным» путем считается схема такая: делаешь find_package(…), а потом одну target_link_libraries(…) и она сама подтягивает все нужные флаги. SDL отстаёт от «передовых практик».

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

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

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

Что ж поделать. Надеюсь плюсовые модули хоть как-то исправят эту ситуацию.

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

Окей, тогда почитаю про find_package и find_library. Может даже попробую разобраться и поправлю, чтобы все работало на find_package, если конечно будет не лень.

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

И каким образом vcpkg избавит от ошибки find_package(Threads)? В довесок при сборке vcpkg тащит блобы и имеет включенную по умолчанию телеметрию.

Скорее всего, у ТС в системе не установлена libc6-dev, поэтому find_package не может найти заголовочники вроде pthtead.h и валится с ошибкой.

На мой взгляд, проверка find_package(Threads) в FindSDL2*.cmake избыточна и может быть удалена.

u-235 ()
Ответ на: комментарий от u-235

Это его избавит от поиска модуля на каких то помойках, кто их кстати будет обновлять, думаешь ОП систему для их обновления настроил? Я думаю нет.

Во вторых кроссплатформа ему нужна, как под виндой ставить все эти библиотеки будешь? Тоже заходя на сайты, ища бинарники под свою версию, а если их нет то собирая через всякие мсусы?

Не читал что там за проблема с pthreads, скорее всего кривой cmake, vcpkg тоже от этого частично избавляет, и показывает сразу после установки пакета как надо его подключать.

У ОПа арч с base-devel, там все присутствовать должно.

В довесок при сборке vcpkg тащит блобы и имеет включенную по умолчанию телеметрию.

Это ПМ а не почтовик, какая разница?

На мой взгляд, проверка find_package(Threads) в FindSDL2*.cmake избыточна и может быть удалена.

))

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

Давно бы открыли изкоробочный FindThreads.cmake и нашли где затык. Там прекрасно видно, какие файлы он чекает и какую тестовую программу пытается компилировать. Как вариант, может в CFLAGS/CXXFLAGS/LDFLAGS флагов напихали, из-за которых падает тестовая компиляция.

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

я все это дело собирал смаке на винлин проблем не было, единственная проблема что это было очень давно и я уже забыл как я это делал, то что я помню что у меня довольно кучерявый сборочный скрипт был и там еще прилинковывалась часть библиотек статически, часть динамически. С таким же успехом смакой можно вообще заскриптовать сначала сборку из исходников и потом подкладывание куда надо и линковку. В общем-то vcpkg он по сути то ничем не лучше, разве что какую-то часть работы уже сделали за тебя, быстрей бинарник получишь без вычитывания документации и написывания сборочных скриптов.

anonymous ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.