Страницы

Поиск по вопросам

Показаны сообщения с ярлыком cmake. Показать все сообщения
Показаны сообщения с ярлыком cmake. Показать все сообщения

понедельник, 30 марта 2020 г.

Как указать cmake где генерировать проект?

#cmake


Нужно сгенерировать проект в другой папке а не текущей. Как это сделать?
    


Ответы

Ответ 1



ответ базируется на ответах к аналогичному вопросу: CMake output/build directory «нормальное» (и ожидаемое пользователями) поведение программы cmake — создавать генерируемые файлы в текущем каталоге. для описанного (редкого) случая, когда текущий каталог, каталог с исходными текстами, и каталог для генерируемых файлов («целевой») — это три разных каталога, можно пойти двумя путями. запускать программу cmake сразу в целевом каталоге. чтобы после выполнения программы оболочка «вернулась» в текущий каталог, можно запускать программу в под-оболочке (используя круглые скобки): ( cd целевой/каталог && cmake каталог/с/исходниками ) указать программе пути к целевому каталогу и каталогу с исходниками с помощью опций -Bпуть и -Hпуть соответственно (пробелов не должно быть): cmake -Bцелевой/каталог -Hкаталог/с/исходниками

воскресенье, 29 марта 2020 г.

Нужно ли добавлять .ui файлы в список исходников cmake?

#cpp #qt #qt5 #cmake #qt_designer


Нужно ли добавлять .ui файлы в список исходников cmake?

То есть писать 

add_executable(my_target main.cpp main.h main.ui)


или 

add_executable(my_target main.cpp main.h)


?
    


Ответы

Ответ 1



Как уже написали, в add_executable указывать *.ui-файлы не обязательно. При включённом set(CMAKE_AUTOUIC ON) cmake сам просмотрит все *.cpp файлы на предмет наличия в них include'ов вида ui_*.h и сам обработает соответствующие *.ui файлы. При сборке без AUTOUIC (по каким-либо причинам), .ui файл необходимо передать макросу qt5_wrap_ui(), который явно создаст команду для сборки ui_*.h, а хедер уже сам подтянется по зависимостям к исходнику, который его включает. С другой стороны это не ошибка, add_executable (и прочие) допускают указание в списке исходников файлы, которые непосредственно не участвуют в сборке; в данном случае они не добавляются в качестве зависимости к конкретной цели. Обычно мотивацией к этому является использование IDE. В этом случае проект для оной, сгенерированный cmake, будет включать их в качестве «дополнительных исходников», и они будут отображаться в списке файлов связанных с целью наряду с остальными. Также, человек, поддерживающий проект, может захотеть указать их просто «для себя», чтобы было явно видно при сборке какого файла используется конкретный ui.

Ответ 2



ui файлы не нужно перечислять в add_executable или add_library - это лишено смысла. Эти файлы обрабатываются с помощью uic, так что это он должен знать о том, где искать эти файлы (именно искать). Если ui файлы находяться в тоже директории, то все норм, а если в другой, то нужно установть опцию: set(CMAKE_AUTOUIC_SEARCH_PATHS "paht/to/uic/files")

Ответ 3



На сегодняшний день я не слышал о прямой поддержке .ui файлов в add_executable(). В этой команде перечисляются лишь исходники, которые CMake умеет "собирать" - .c,.cpp,.h,.o,.asm. Файлы .ui обрабатываются специальным макросом qt5_wrap_ui() из модуля Qt5Widgets. См. документацию.

воскресенье, 9 февраля 2020 г.

Как прилинковать нестандартную версию protobuf используя cmake

#cpp #cmake #protobuf #кросс_компиляция #линковка


Есть проект под arm который компилируется и собирается на х86ой машине (кросскомпиляция).
Есть версия библиотеки protobuf собранная под arm по этой 
инструкции. В cmake файле я пытаюсь явно указать местоположение собранной под arm
библиотеки через переменную Protobuf_SRC_ROOT_FOLDER но похоже что cmake эта переменная
вообще побоку. Что мне сделать что бы find_package(Protobuf REQUIRED) нашёл ту версию
protobuf которая мне нужна?

cmake_minimum_required(VERSION 2.8)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -pthread ") #-lboost_system
project(proto_test)

# Подключаем протобуф 
set (Protobuf_SRC_ROOT_FOLDER "/home/mrfieldy/prot_build/protobuf-3.5.1-arm/src")  
#set (Protobuf_USE_STATIC_LIBS ON)   
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto)
add_executable(${PROJECT_NAME} test.pb.cc ${PROTO_SRCS} ${PROTO_HDRS} "main.cpp")
target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})




Ответ:

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

cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -pthread ")
project(proto_test)
# Подключаем протобуф 
find_package(Protobuf REQUIRED)
set (PROTOBUF_INCLUDE_DIRS "/home/mrfieldy/prot_build/protobuf-3.6.0-arm/src/")
set (PROTOBUF_LIBRARIES "/home/mrfieldy/prot_build/protobuf-3.6.0-arm/src/.libs/libprotobuf.so")
include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
#protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto)
add_executable(${PROJECT_NAME} test.pb.cc ${PROTO_SRCS} ${PROTO_HDRS} "main.cpp")
target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})

    


Ответы

Ответ 1



Поискал по переменной Protobuf_SRC_ROOT_FOLDER и нашел вот что: FindProtobuf К сожалению мой английский sehr schlecht, но, насколько я понял у вас версия cmake слишком низкая (документация там начинается с 3.02), а сама переменная касается лишь определенного случая, касающегося Visual Studio и, что-то мне подсказывает, это не то, что вы используете. Посоветую написать Find-файл самому - это довольно просто

Ответ 2



У нас похожая ситуация, только QtCreator. Может поможет. Это переменные конфигурации CMake А это toolchain (если собирать не в QtCreator, а в консоли): set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(buildrootdir /home/vegorov/Build-Root/04.06.2018/BR-opo) set(buildtriplet arm-buildroot-linux-gnueabihf) set(CMAKE_SYSROOT ${buildrootdir}/output/host/${buildtriplet}/sysroot) set(CMAKE_STAGING_PREFIX ${buildroot}/output/spo-stage) set(tools ${buildrootdir}/output/host/) set(CMAKE_C_COMPILER ${tools}/bin/${buildtriplet}-gcc) set(CMAKE_CXX_COMPILER ${tools}/bin/${buildtriplet}-g++) set(PROTOBUF_PROTOC_EXECUTABLE "${tools}bin/protoc") set(CMAKE_PREFIX_PATH ${buildrootdir}/output/host/${buildtriplet}/sysroot/usr/lib/cmake) set(OE_QMAKE_PATH_EXTERNAL_HOST_BINS ${tools}/bin/) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(COMPILER_FLAGS "--sysroot=${CMAKE_SYSROOT} -O2 -march=armv7-a -marm -mfpu=vfpv3-d16 -mfloat-abi=hard -mcpu=cortex-a9") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILER_FLAGS}" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS}" CACHE STRING "" FORCE) #set(envpath $ENV{PATH}) #set(ENV{PATH} "${tools}bin:${envpath}" ) #message(STATUS ":${tools}bin:${envpath}")

системы сборки c++ в qt

#cpp #qt #cmake #qmake #qbs


Переустановив qt (звучит как прям история,minGW для qt на windows 64-bit(и не только))
и отогнав сомнения насчет minGW я захотел в qt creator написать hello world...

И тут задумался:что за системы сборок? Пользовался qmake(потому что по дефолту стояла).

Короче можете простыми словами объяснить что такое qmake,Cmake,Qbs...Пожалуйста
    


Ответы

Ответ 1



qmake - система сборки, родная для Qt. Не знаете что использовать - берите ее. Нативно работает с QtCreator. Cmake - популярная система сборки. Умеет собирать разнообразные проекты под разнообразные оси/среды разработки. Умеет собирать и Qt проекты, но требует немного "телодвижений". QtCreator умеет с ней хорошо работать, но иногда как то оно странно (но может это мне везет). qbs - попытка "исправить qmake", написать все заново и правильно. Также всякие новомодные штуки - json подобный стиль файла проекта, модули, сборки под разные оси. почитать холивора на lor от самий разработчиков Qt статистика

пятница, 24 января 2020 г.

Как компилировать на Linux и на Windows одновременно, используя CMake?

#cpp #linux #windows #cmake #cross_compiling


Я пишу всё с Linux-а, и все проекты, соответственно, собираются исключительно под Linux.
Недавно я нашёл, что с помощью MinGW можно компелировать с Линукса проекты на винду.
Попробовал "Hello, World!" - проверил - получилось. Это меня обрадовало. Попробовал
немножечко переделать один из своих давних проектов, который использовал несколько
сторонних библиотек, и вот тут начались трудности.

Очевидно, что для Windows пойдут только соответствующие библиотеки. Скачал, вроде
всё правильно настроил в CMake-е, но... Любимый undefined  reference встретил меня
с улыбкой.

Мой CMake:

cmake_minimum_required(VERSION 3.10)
project(DiSqProj)

set(CMAKE_CXX_STANDARD 17)


if (false) # Unix

    message("Building project for Unix.")

    set(LIBS
        -lGL -lGLEW -lglfw
        -lsfml-graphics
        -lsfml-window
        -lsfml-system)

elseif(true) # Win64

    message("Building project for Win64.")

    set(WIN_LIBS_DIR
        /home/prunkles/Dev/CLionProjects/WinLibs)

    set(INCLUDE_DIRS
        PUBLIC ${WIN_LIBS_DIR}/glew-2.1.0/include # GLEW include
        PUBLIC ${WIN_LIBS_DIR}/glfw-3.2.1/include # GLFW include
        PUBLIC ${WIN_LIBS_DIR}/SFML-2.5.0/include # SFML include
        PUBLIC ${WIN_LIBS_DIR}/glm/include # GLM include
    )

    set(LINK_DIRS
        ${WIN_LIBS_DIR}/glew-2.1.0/lib/Release/x64 # GLEW lib
        ${WIN_LIBS_DIR}/glfw-3.2.1/lib-mingw-w64 # GLFW lib
        ${WIN_LIBS_DIR}/SFML-2.5.0/lib # SFML lib
    )

    set(LIBS
        glew32s
        glfw3
        sfml-graphics
        sfml-window
        sfml-system
    )

endif()

link_directories(${LINK_DIRS})

add_executable(${PROJECT_NAME}
    main.cpp
    DiamondSquare.cpp DiamondSquare.h
    rand-adv.h
    inWin3D.cpp
    inWin2D.cpp inFiles.cpp
    ViewTypes.h
    genImageFromMap.cpp genImageFromMap.h
    Camera.cpp Camera.h
    GLLoadShaders.h)

target_include_directories(${PROJECT_NAME}
    ${INCLUDE_DIRS})

target_link_libraries(${PROJECT_NAME}
    ${LIBS})

    


Ответы

Ответ 1



Приведённый Вами пример плох тем, что в нём явно указаны библиотеки и хедеры, которые, вообще говоря, зависят от платформы. Не надо так делать. Используемые Вами библиотеки имеют или поставляют сами описания для их сборки/подключения в проект в виде так называемого пакета, который следует подключить с помощью find_package. Вначале как обычно: cmake_minimum_required(VERSION 3.10) project(DiSqProj) set(CMAKE_CXX_STANDARD 17) Затем ищем зависимости: find_package(OpenGL) find_package(GLEW) С этими пакетами все хорошо, они есть в самом CMake, а вот с GLFW оказалось не так просто - не find_package(GLFW) find_package(glfw3 3.3 REQUIRED) find_package(SFML COMPONENTS graphics window system) add_executable(${PROJECT_NAME} main.cpp DiamondSquare.cpp DiamondSquare.h rand-adv.h inWin3D.cpp inWin2D.cpp inFiles.cpp ViewTypes.h genImageFromMap.cpp genImageFromMap.h Camera.cpp Camera.h GLLoadShaders.h) target_link_libraries(${PROJECT_NAME} OpenGL::OpenGL GLEW::GLEW glfw sfml-graphics sfml-window sfml-system) Возможно, помимо OpenGL::OpenGL потребуются и другие модули (OpenGL::GLX, OpenGL::GLU, например). Вся прелесть таких импортируемых модулей, что не требуется заботится об target_include_directories - все ссылки на либы и пути до хедеров уже добавлены. Теперь можно сменить не только ОС, но и компилятор :). Правда сторонние либы придётся собрать под правильный компилятор.

понедельник, 6 января 2020 г.

Как подружить wxWidgets и CLion (Windows + mingw-w64)?

#c #cmake #сборка #clion #wxwidgets


Хочу сделать GUI приложение и выбрал для этого Си (без ++) и wxWidgets. Скачал с
офф.сайта установщик, поставил (Установился в C:\wxWidgets-3.1.1, но я кинул рядом
с исходниками папку с библиотекой в папке wx есть файл, который просится в коде).

 

Думал, что на этом всё, но нет, при попытке компиляции вылазит ошибка, что нет библиотеки.

Ошибка:


  "C:\Program Files\JetBrains\CLion 2018.1.5\bin\cmake\bin\cmake.exe" --build C:\Users\Timoshka-WIN10\Documents\CLionProjects\GuiTEST\cmake-build-debug
--target GuiTEST -- -j 1
      [ 50%] Building C object CMakeFiles/GuiTEST.dir/main.c.obj
      C:\Users\Timoshka-WIN10\Documents\CLionProjects\GuiTEST\main.c:3:10: fatal
error: wx/wxprec.h: No such file or directory
       #include 
                ^~~~~~~~~~~~~
      compilation terminated.
      mingw32-make.exe[3]: * [CMakeFiles\GuiTEST.dir\build.make:62: CMakeFiles/GuiTEST.dir/main.c.obj]
Error 1
      mingw32-make.exe2:  [CMakeFiles\Makefile2:67: CMakeFiles/GuiTEST.dir/all] Error 2
      mingw32-make.exe1:  [CMakeFiles\Makefile2:79: CMakeFiles/GuiTEST.dir/rule] Error 2
      mingw32-make.exe: * [Makefile:117: GuiTEST] Error 2


CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(GuiTEST C)

set(CMAKE_C_STANDARD 11)

add_executable(GuiTEST main.c)

target_include_directories ( GuiTEST PUBLIC
        $< BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}libs/wxWidgets-3.1.1/include >
        $< INSTALL_INTERFACE:libs/wxWidgets-3.1.1/include >  # /include/mylib
        )


Код с офф.сайта wxWidgets

// wxWidgets "Hello World" Program
// For compilers that support precompilation, includes "wx/wx.h".
#include 
#ifndef WX_PRECOMP
    #include 
#endif
class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};
class MyFrame : public wxFrame
{
public:
    MyFrame();
private:
    void OnHello(wxCommandEvent& event);
    void OnExit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);
};
enum
{
    ID_Hello = 1
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
    MyFrame *frame = new MyFrame();
    frame->Show(true);
    return true;
}
MyFrame::MyFrame()
    : wxFrame(NULL, wxID_ANY, "Hello World")
{
    wxMenu *menuFile = new wxMenu;
    menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
                     "Help string shown in status bar for this menu item");
    menuFile->AppendSeparator();
    menuFile->Append(wxID_EXIT);
    wxMenu *menuHelp = new wxMenu;
    menuHelp->Append(wxID_ABOUT);
    wxMenuBar *menuBar = new wxMenuBar;
    menuBar->Append(menuFile, "&File");
    menuBar->Append(menuHelp, "&Help");
    SetMenuBar( menuBar );
    CreateStatusBar();
    SetStatusText("Welcome to wxWidgets!");
    Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
    Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
    Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
}
void MyFrame::OnExit(wxCommandEvent& event)
{
    Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& event)
{
    wxMessageBox("This is a wxWidgets Hello World example",
                 "About Hello World", wxOK | wxICON_INFORMATION);
}
void MyFrame::OnHello(wxCommandEvent& event)
{
    wxLogMessage("Hello world from wxWidgets!");
}


Говорят, что надо что-то подшаманить в CMakeLists.txt, или добавить target_include_directories,
но в первом случае вроде под Ubuntu и не понятно, а во втором и по официальному мануалу
для CMake тоже ничего не понятно :).
    


Ответы

Ответ 1



В CMake есть команда find_package. Поиск wxWidgets должен выглядеть так : cmake_minimum_required(VERSION 2.8) project(MySuperProgram) find_package(wxWidgets REQUIRED) add_executable(${PROJECT_NAME} "main.cpp") target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) target_link_libraries(${PROJECT_NAME} ${wxWidgets_LIBRARIES}) target_compile_definitions(${PROJECT_NAME} PRIVATE ${wxWidgets_DEFINITIONS}) target_include_directories(${PROJECT_NAME} PRIVATE ${wxWidgets_INCLUDE_DIRS}) У меня linux и этого вполне хватает чтобы скомпилировать проект Hello World. Я wxWidgets не использовал. Но по описаниям он написан на C++. Даже в вашем примере код C++. Не уверен что будет легко использовать wxWidgets с языком С.

Ответ 2



target_include_directories( GuiTEST PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libs/wxWidgets-3.1.1/include

воскресенье, 22 декабря 2019 г.

OpenGL 4 со стандартного Windows SDK

#cpp #windows #opengl #cmake


хотел подключить OpenGL 4 стандартными средствами Windows SDK ко своему проекту на
С++, не используя сторонние библиотеки на подобии glut, glfw и т.д.. Opengl 1 подключался
прекрасно, когда я использовал следующее:

// В файлах проекта:
#include 
#include 
#include 

// в CMake
target_link_libraries (ProjectName opengl32.lib glu32.lib)


Но а вот когда я решил использовать функции шейдеров, VAO, VBO, то их просто не оказалось,
но думаю старая версия OpenGL стоит на винде... Скачал OpenGL Extension Viewer и как
оказалось, была у меня установлена OpenGL 1.1. После чего я обновил OpenGL до версии
4.4, но у меня так и не получается использовать функции шейдеров, VAO, VBO. Хотел спросить
может каких хедеров не хватает или стоит еще дополнительные библиотеки прилинковать
или что-то я не дообновил?
    


Ответы

Ответ 1



Дело в том, что системная библиотека opengl32.dll предоставляет только базовые функции, существовавшие во время OpenGL 1.1. Доступ к более новым возможностям можно получить с помощью функции wglGetProcAddress(). В качестве параметра ей необходимо передать имя требуемой функции, а возвращаемый указатель — преобразовать в тип PFNИМЯФУНКЦИИPROC (типы объявлены в ). Пример: const PFNGLCOMPILESHADERPROC _glCompileShader = reinterpret_cast(wglGetProcAddress("glCompileShader")); Примечание: для работы с OpenGL таким способом требуется наличие трёх заголовочных файлов, отсутствующих в стандартной поставке Windows SDK. Эти файлы необходимо скачать с сайта компании-создателя OpenGL и разместить в папке проекта следующим рекомендуемым образом: https://www.khronos.org/registry/OpenGL/api/GL/glext.h → папка_проекта/include/GL/glext.h https://www.khronos.org/registry/OpenGL/api/GL/wglext.h → папка_проекта/include/GL/wglext.h https://www.khronos.org/registry/EGL/api/KHR/khrplatform.h → папка_проекта/include/KHR/khrplatform.h При этом необходимо указать CMake на наличие этих файлов: target_include_directories (ProjectName include) Также необходимо вручную создать контекст, поддерживающий OpenGL 4. Создание OpenGL-контекста происходит в два этапа: Сначала создаём контекст версии 1.1 для корректной работы wglGetProcAddress(). Затем получаем указатель на функцию wglCreateContextAttribsARB() и используем её для создания уже нужного нам контекста. Ниже приведены функции создания и уничтожения контекста: #include #include #define WGL_WGLEXT_PROTOTYPES #include // Параметры начального контекста static const PIXELFORMATDESCRIPTOR pfd = { /* nSize */ sizeof(PIXELFORMATDESCRIPTOR), /* nVersion */ 1, /* dwFlags */ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, /* iPixelType */ PFD_TYPE_RGBA, /* cColorBits */ 32, /* c...Bits|Shift */ 0, 0, 0, 0, 0, 0, 0, 0, /* cAccum...Bits */ 0, 0, 0, 0, 0, /* cDepthBits */ 16, /* cStencilBits */ 0, /* cAuxBuffers */ 0, /* iLayerType */ PFD_MAIN_PLANE, /* bReserved */ 0, /* dw...Mask */ 0, 0, 0 }; // Параметры конечного контекста (OpenGL 4.0 Core) static const int context_attributes[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 4, WGL_CONTEXT_MINOR_VERSION_ARB, 0, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0 }; // Функция для создания контекста OpenGL 4. Принимает HWND окна вывода, возвращает // дескриптор GL-контекста. HGLRC gl_init(HWND default_output) { const HDC canvas = GetDC(default_output); // Этап 1 HGLRC gl = NULL; const int format = ChoosePixelFormat(canvas, &pfd); if (format != 0) { SetPixelFormat(canvas, format, &pfd); const HGLRC gl_boostrap = wglCreateContext(canvas); wglMakeCurrent(canvas, gl_boostrap); // Этап 2 gl = reinterpret_cast (wglGetProcAddress("wglCreateContextAttribsARB")) (canvas, NULL, context_attributes); wglMakeCurrent(canvas, gl); wglDeleteContext(gl_boostrap); } // Удаляем более не требуемый начальный контекст и возвращаем конечный ReleaseDC(default_output, canvas); return gl; } // Функция для уничтожения GL контекста. Принимает HWND окна вывода и дескриптор // GL-контекста. Можно было бы ограничиться и HWND, но у некоторых драйверов для // интегрированной графики Intel функция wglMakeCurrent() не работает при нулевом // значении параметра с GL-дескриптором. void gl_release(HWND default_output, HGLRC gl) { const HDC hdc = GetDC(default_output); wglMakeCurrent(hdc, NULL); ReleaseDC(default_output, hdc); wglDeleteContext(gl); }

четверг, 19 декабря 2019 г.

Как находить библиотеки с помощью CMake?

#cpp #cmake


У меня в проекте используются библиотеки Boost и WebRTC. При попытке собрать проект
возникает проблема со сборкой WebRTC вот скриншот. 

CMakeLists.cmake:

cmake_minimum_required(VERSION 3.9)

project(webrtc-server)

if(EXISTS "${CMAKE_SOURCE_DIR}/LocalConfig.cmake")
  include(LocalConfig.cmake)
else()
  message(FATAL_ERROR "Local config is absent")
endif()

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")

set (Boost_USE_MULTITHREADED ON)
set (Boost_USE_STATIC_LIBS ON)
set (Boost_USE_STATIC_RUNTIME OFF)
set (BOOST_ALL_DYN_LINK OFF)

include(CMake/CMakeFindExtensions.cmake)
include(CMake/CMakeHelpers.cmake)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")

find_package(Boost 1.65.1 REQUIRED COMPONENTS program_options system)
find_package(WebRTC REQUIRED)

include_directories(${Boost_INCLUDE_DIR})
include_directories(${WEBRTC_INCLUDE_DIR})

message(SOURSE " ${Boost_LIBRARIES}")
message(SOURSE " ${Boost_INCLUDE_DIRS}")

if(Boost_FOUND)
    add_executable(webrtc-server
            src/webrtc_server.cpp
            src/webrtc_observers.h
    )
    target_link_libraries(webrtc-server
            ${Boost_LIBRARIES}
            ${WEBRTC_LIBRARIES}
    )
endif()


LocalConfig.cmake:

set(BOOST_ROOT ExternalLibs/boost_1_65_1)
set(WEBRTC_ROOT_DIR ExternalLibs/WebRTC)


Tree :

.
├── CMake
│   ├── CMakeFindExtensions.cmake
│   ├── CMakeHelpers.cmake
│   └── FindWebRTC.cmake
├── CMakeLists.txt
├── ExternalLibs
│   ├── boost_1_65_1
│   └── WebRTC
├── LocalConfig.cmake
├── README.md
├── scripts
│   ├── install_boost.sh
│   └── install_webrtc.sh
├── src
│   ├── webrtc_observers.h
│   └── webrtc_server.cpp
└── temp


P.S. В шапке верная версия. Советую внимательно смотреть на регистр переменных -
имеет очень важное значение.
    


Ответы

Ответ 1



Поиск библиотек в CMake происходит с использованием базовых команд самого CMake, для поиска по файловой системе. Это такие команды как: find_path, find_library и т.д. Обычному пользователю, как правило, эти команды не нужны, потому что уже кто-то заранее написал скрипт CMake, состоящий из этих команд, который находит всю необходимую информацию по библиотеке/фреймворку. Обычно такие скрипты имеют вид FindXXX.cmake, где XXX это имя библиотеки. Эти скрипты используются тогда, когда пользователь в своём CMake скрипте использует команду find_package. К примеру, find_package(Boost REQUIRED) ожидает найти файл FindBoost.cmake и когда находит его, то исполняет всё, что находится внутри этого файла. CMake поставляется с целым набором таких файлов, которые можно найти в директории, где он установлен: share/cmake-xxx/Modules. Имея это список файлов мы можем посмотреть, что за библиотеки поддерживаются CMake из коробки, а также посмотреть, что могут потребовать соответствующие скрипты на вход, чтобы помочь найти ту или иную библиотеку. Итак, мы перешили в эту директорию и нашли FindBoost.cmake. Благо этот скрипт имеет неплохую документацию, и из него мы сразу узнаём, что для помощи в нахождении boost, ему необходимо знать где находится папка с оным. Для этого он ждёт переменную BOOST_ROOT. Эта переменная может быть установлена как локально в скрипте CMake, так и глобально, как переменная окружения. Т.е. для того, чтобы нам найти boost, мы можем написать следующее: set(BOOST_ROOT /home/koshachok/proj/ExternalLibs/Boost_1_65_1) find_package(Boost REQUIRED COMPONENTS program_options system) Но явно прописывать путь в общем файле это неправильно, лучше используйте переменную окружения или же некоторый обходной путь, который я опишу дополнительно позже. Заметьте, что каждый скрипт уникален и то, что ожидает скрипт для boost, может отличаться от того, что требует другая библиотека. Поэтому всегда нужно смотреть документацию к скрипту, чтобы понять, чего он от тебя хочет. Если у скрипта хорошая документация, то всё сразу будет понятно. Если нет, тогда придётся из его содержимого понять самостоятельно, чего же он хочет (обычно это не так сложно). Вооружившись всем вышеописанным идём искать FindWebRTC.cmake в директории CMake и не находим его. Что делать? Первым делом вбиваем в Яндекс FindWebRTC.cmake и, как правило, находим немало вариантов уже готового файла, один из котороых можно выбрать под свои нужды. Я взял первый попавшийся, и он ожидает установленной WEBRTC_ROOT_DIR в качестве помощи в поиске. Но как нам использовать этот файл, как сделать так, чтобы find_package его использовал? Очень просто: помещаем его в дерево исходников, скажем в 3rdParty/cmake. После чего добавляем в наш скрипт (до find_package) такую строку: list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/3rdParty/cmake") После чего, скрипт должен находиться и выполняться. Нам же остаётся использовать его результаты (WEBRTC_INCLUDE_DIR, WEBRTC_LIBRARIES). Пару слов хочется сказать по поводу того, как и где прописывать полные пути к директориям библиотек, которые помогают скриптам в поиске. Для этого я использую следующий механизм. В основном скрипте CMake добавляем такой код: if(EXISTS "${CMAKE_SOURCE_DIR}/LocalConfig.cmake") include(LocalConfig.cmake) else() message(FATAL_ERROR "Local config is absent") endif() После чего добавляем файл LocalConfig.cmake со следующим содержимым: set(BOOST_ROOT /home/koshachok/proj/ExternalLibs/Boost_1_65_1) set(WEBRTC_ROOT_DIR /home/koshachok/proj/ExternalLibs/WebRTC) И, собственно, всё. Каждый разработчик просто создаёт свой локальный конфиг, который никак не мешает основному файлу CMake.

воскресенье, 15 декабря 2019 г.

CMake не видит компилятора

#cpp #c #g++ #cmake #сборка


Поставил CMake (без CLang), добавил в переменную path путь к cmake-3.9.2/bin.

cmake -version 


работает. 

Есть CMakeLists.txt файл

#cmake

cmake_minimum_required(VERSION 3.5)

project(concentration)

option(set_clang "set clang as default compiler" 0)
option(set_gpp "set g++ as default compiler" 0)
option(cros_compile "cros compile for win32" 0)

if(${UNIX})
    message(STATUS "Unix system")
elseif(${WIN32})
    message(WARNING "Work is not guaranted")
else()
    message(FATAL_ERROR "System not supported")
endif()

if(set_gpp)
    set(CMAKE_CXX_COMPILER g++)
endif()
if(set_clang)
    set(CMAKE_CXX_COMPILER clang++)
endif()
if(cros_compile)
    set(PROJECT_NAME ${PROJECT_NAME}.exe)
    set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++-posix)
    set(CMAKE_CXX_FLAGS "-static-libstdc++ -static-libgcc")
endif()

message(STATUS "Project " ${PROJECT_NAME})
message(STATUS "cxx compiler " ${CMAKE_CXX_COMPILER})

add_definitions(-Wall -std=c++14)

include_directories(include)

set(MAIN_SRC sources/main.cpp)
file(GLOB CONCENTRATION_SRC "sources/concentration/*.cpp")

if(cros_compile)
    find_package(PDCurses REQUIRED)
else()
    find_package(Curses REQUIRED)
endif()

include_directories(${CURSES_INCLUDE_DIR})

add_executable(${PROJECT_NAME} ${MAIN_SRC} ${CONCENTRATION_SRC})

target_link_libraries(${PROJECT_NAME} ${CURSES_LIBRARIES})


в общем когда запускаю командами

cmake
cmake -Dset_gpp=1 


CMake пишет:


-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:5 (project):
  The CMAKE_C_COMPILER:

    cl

  is not a full path and was not found in the PATH.

  To use the NMake generator with Visual C++, cmake must be run from a shell
  that can use the compiler cl from the command line.  This environment is
  unable to invoke the cl compiler.  To fix this problem, run cmake from the
  Visual Studio Command Prompt (vcvarsall.bat).

  Tell CMake where to find the compiler by setting either the environment
  variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
  the compiler, or to the compiler name if it is in the PATH.


CMake Error at CMakeLists.txt:5 (project):
  The CMAKE_CXX_COMPILER:

    cl

  is not a full path and was not found in the PATH.

  To use the NMake generator with Visual C++, cmake must be run from a shell
  that can use the compiler cl from the command line.  This environment is
  unable to invoke the cl compiler.  To fix this problem, run cmake from the
  Visual Studio Command Prompt (vcvarsall.bat).

  Tell CMake where to find the compiler by setting either the environment
  variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
  to the compiler, or to the compiler name if it is in the PATH.


-- Configuring incomplete, errors occurred!
See also "../CMakeFiles/CMakeOutput.log".
See also "../CMakeFiles/CMakeError.log".



Путь к компилятору есть в path. g++ команда работает. Постоянно компилирую с командной
строки. Пробовал в CmakeLists.txt указывать явный путь к g++. Все равно не помогает.
Все пути к файлам - латиница.

В общем, нужна помощь!
    


Ответы

Ответ 1



В Windows, судя по исходникам, CMake по дефолту (если генератор не указан явно) пробует найти (по записям в реестре) самую свежую версию Visual Studio, а если не находит, использует NMake. Таким образом, если у вас установлена Студия (или просто остался мусор в реестре, в результате некорректного удаления студии или по другим, гораздо более серьезным причинам), то CMake будет делать проект под самую свежую из установленных Студий. Чтобы явно указать нужный вам генератор, используйте ключик -G: cmake -G "MinGW Makefiles"

среда, 10 июля 2019 г.

Линковка своих динамических библиотек к исполняемому файлу

Пишу Makefile для проекта, который использует стороннюю динамическую библиотеку. Библиотека лежит в определённой директории, не входящей в список дефолтных.
Компиляция проходит успешно. Проблемы, очевидно, с запуском - не может найти библиотеку.
Можно ли составить Makefile так, чтобы он выполнял функцию, аналогичную функции link_directories в CMake? То есть, чтобы в исполняемый файл был как бы "зашит" путь до библиотеки.


Ответ

Согласно man ld нужно сообщить линкеру параметр -rpath=тот_самый_путь к библиотекам, который нужно зашить в бинарник. Сделать это можно двумя способами. Через опцию gcc -Xlinker -rpath=тот_самый_путь. Если вы используете правила сборки make по-умолчанию, для этих опций подходит переменная LDFLAGS в Makefile:
LDFLAGS+= -Xlinker -rpath=тот_самый_путь
Второй способ -- минуя gcc через переменную окружения LD_RUN_PATH которую ld читает сам в случае, если опции -rpath не было. В Makefile для этого можно написать:
export LD_RUN_PATH=тот_самый_путь
Или написать LD_RUN_PATH=тот_самый_путь перед $(CC) непосредственно в правиле для линковки.
В пути может присутствовать подстрока $ORIGIN, вместо которой будет подставлен путь к каталогу, содержащему исполняемый файл. См. man ld-linux.so. Пример строки в Makefile:
myprogram: LDFLAGS+= -Xlinker -rpath='$$ORIGIN/' myprogram: myprogram.o

суббота, 6 июля 2019 г.

cmake, qt и проект разнесенный по каталогам

Вопрос вытек из моего предыдущего вопроса: cmake & qt проблемы
Оказалось, что если все файлы закинуть в одну папку, то все успешно компилируется, но стоит их разнести по разным каталогам, как все перестает работать... Тобишь: если заголовочный файл для класса с Q_OBJECT разместить в том же каталоге, что и .cpp файл с реализацией этого класса - то все работает. Но если заголовочный файл вынести в папку include, то все накрывается медным тазом.
Почему? Можно ли все-таки собирать подобные проекты для qt и как это сделать?


Ответ

Ваш заголовочный файл не был указан в списке, передаваемом в add_executable()
По умолчанию CMake пытается для каждого известного *.cpp найти в той же папке его *.h‐ или *.hpp‐пару. Благодаря этому ваш изначальный случай и собирался как задумано — CMake угадывал имя и расположение заголовочного файла и передавал его moc-у вместе со всеми прочими заголовочными файлами.
Про вашу же папку include CMake ничего не знает. Поэтому необходимо сделать одно из двух
явно поместить заголовочный файл (или файлы по glob-маске) в проект (то есть куда-нибудь внутрь add_executable()), давая возможность обработать этот файл всем, кто подписался на обработку *.hpp, в том числе и moc либо воспользоваться тем, что moc, встретив при сканировании *.cpp-файла конструкцию вида #include "moc_имя.cpp", начинает искать для обработки файл имя.h/имя.hpp во всех местах, указанных как папки с заголовочными файлами (в том числе и по списку include_directories()). Иными словами, надо заменить строку:
#include "calculator.hpp"
на:
#include "moc_calculator.cpp"

понедельник, 15 апреля 2019 г.

Как прилинковать нестандартную версию protobuf используя cmake

Есть проект под arm который компилируется и собирается на х86ой машине (кросскомпиляция). Есть версия библиотеки protobuf собранная под arm по этой инструкции. В cmake файле я пытаюсь явно указать местоположение собранной под arm библиотеки через переменную Protobuf_SRC_ROOT_FOLDER но похоже что cmake эта переменная вообще побоку. Что мне сделать что бы find_package(Protobuf REQUIRED) нашёл ту версию protobuf которая мне нужна?
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -pthread ") #-lboost_system project(proto_test)
# Подключаем протобуф set (Protobuf_SRC_ROOT_FOLDER "/home/mrfieldy/prot_build/protobuf-3.5.1-arm/src") #set (Protobuf_USE_STATIC_LIBS ON) find_package(Protobuf REQUIRED) include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto) add_executable(${PROJECT_NAME} test.pb.cc ${PROTO_SRCS} ${PROTO_HDRS} "main.cpp") target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})

Ответ:
В общем, как посоветовали ниже, я выбрал путь сначала выполнить find_package, а потом с помошью set переопределить пути. Долго искал на какие пути надо переопределить. Вот рабочий вариант.
cmake_minimum_required(VERSION 2.8) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -pthread ") project(proto_test) # Подключаем протобуф find_package(Protobuf REQUIRED) set (PROTOBUF_INCLUDE_DIRS "/home/mrfieldy/prot_build/protobuf-3.6.0-arm/src/") set (PROTOBUF_LIBRARIES "/home/mrfieldy/prot_build/protobuf-3.6.0-arm/src/.libs/libprotobuf.so") include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) #protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto) add_executable(${PROJECT_NAME} test.pb.cc ${PROTO_SRCS} ${PROTO_HDRS} "main.cpp") target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})


Ответ

Поискал по переменной Protobuf_SRC_ROOT_FOLDER и нашел вот что:
FindProtobuf
К сожалению мой английский sehr schlecht, но, насколько я понял у вас версия cmake слишком низкая (документация там начинается с 3.02), а сама переменная касается лишь определенного случая, касающегося Visual Studio и, что-то мне подсказывает, это не то, что вы используете.
Посоветую написать Find-файл самому - это довольно просто

системы сборки c++ в qt

Переустановив qt (звучит как прям история,minGW для qt на windows 64-bit(и не только)) и отогнав сомнения насчет minGW я захотел в qt creator написать hello world...
И тут задумался:что за системы сборок? Пользовался qmake(потому что по дефолту стояла).
Короче можете простыми словами объяснить что такое qmake,Cmake,Qbs...Пожалуйста


Ответ

qmake - система сборки, родная для Qt. Не знаете что использовать - берите ее. Нативно работает с QtCreator. Cmake - популярная система сборки. Умеет собирать разнообразные проекты под разнообразные оси/среды разработки. Умеет собирать и Qt проекты, но требует немного "телодвижений". QtCreator умеет с ней хорошо работать, но иногда как то оно странно (но может это мне везет). qbs - попытка "исправить qmake", написать все заново и правильно. Также всякие новомодные штуки - json подобный стиль файла проекта, модули, сборки под разные оси. почитать холивора на lor от самий разработчиков Qt статистика

четверг, 21 марта 2019 г.

Слинковать CMake с еще не собранным таргетом

Есть директория с компонентами, все из которых являются статическими библиотеками. Они лежат в общей папке, каждая компонента имеет свой CMakeLists.txt и может собраться отдельно через CMake.
Также есть несколько утилит, каждая из которых может тянуть свои зависимости.
Пример иерархия папок:
[ git ] - libraries - strings - my_math - media_converter - logger - utilities - calc - video_player
Примеры CMakeLists.txt:
Для библиотеки:
project( library_name ) add_library( ${PROJECT_NAME} STATIC < .. > )
Для утилиты:
project( utility_name ) add_executable( ${PROJECT_NAME} < .. > )
# import components :
add_subdirectory( <..> ) # компонента еще не собрана, собираем ее target_include_directories( <..> ) # добавляю пути к заголовкам компоненты target_link_libraries( <..> ) # линкуем к таргету 'utility_name' библиотеки компоненты
Таким образом, если одна из импортируемых компонент тянет что-нибудь еще, например, media_converter тянет за собой ffmpeg и когда я добавлю media_converter к video_player, то в CMakeLists.txt у video_player придется добавить конструкции типа "find_library( ffmpeg )", "target_link ..", чтобы разрешить все зависимости.
Вопрос в следующем. Как посредством CMake в скрипте для статической библиотеки указать утилите, которой ее использует, сразу подтягивать внешние зависимости компоненты?
Я попытался в CMakeLists.txt для компоненты использовать такую конструкцию:
project( library_name ) add_library( ${PROJECT_NAME} STATIC < .. > ) target_link_libraries( ${CMAKE_PROJECT_NAME} < .. > )
По документации CMAKE_PROJECT_NAME - это название проекта для которого вызван CMake, т.е. в моем случае - это video_player. Но при таком раскладе у меня возникает ошибка - я пытаюсь слинковать компоненту с несуществующим таргетом.
Кто-нибудь сталкивался с такой проблемой? Пока не смог найти решение самостоятельно.


Ответ

Структура
├── libs │   └── media_converter │   ├── CMakeLists.txt │   └── main.cpp └── utils └── video_player ├── CMakeLists.txt └── main.cpp
media_converter
Сшздаём статическую библиотеку media_converter, находим и линкуем к ней зависимости. Обрати внимание, что зависимости публичные (PUBLIC).
cmake_minimum_required(VERSION 3.10) project(media_converter CXX)
add_library(${PROJECT_NAME} STATIC main.cpp)
find_library(MPG123_LIB mpg123) target_link_libraries(${PROJECT_NAME} PUBLIC ${MPG123_LIB}) target_include_directories(${PROJECT_NAME} PUBLIC /some/secret/path/to/mpg123)
video_player
Создаём приложение video_player и линкуемся с media_converter. Это автоматически добавит все публичные зависимости media_converter к video_player
cmake_minimum_required(VERSION 3.10) project(video_player CXX)
add_executable(${PROJECT_NAME} main.cpp)
add_subdirectory(../../libs/media_converter media_converter) target_link_libraries(${PROJECT_NAME} media_converter)
Проверка
$ cmake ../utils/video_player/ ... Build files have been written to: .../build
$ make VERBOSE=1 ... [ 75%] Building CXX object CMakeFiles/video_player.dir/main.cpp.o /usr/bin/c++ -I/some/secret/path/to/mpg123 -o CMakeFiles/video_player.dir/main.cpp.o -c .../utils/video_player/main.cpp [100%] Linking CXX executable video_player /usr/bin/cmake -E cmake_link_script CMakeFiles/video_player.dir/link.txt --verbose=1 /usr/bin/c++ CMakeFiles/video_player.dir/main.cpp.o -o video_player media_converter/libmedia_converter.a /usr/lib64/libmpg123.so
Как видно, video_player компилируется с -I/some/secret/path/to/mpg123 и линкуется с /usr/lib64/libmpg123.so

пятница, 15 февраля 2019 г.

CMake не видит компилятора

Поставил CMake (без CLang), добавил в переменную path путь к cmake-3.9.2/bin
cmake -version
работает.
Есть CMakeLists.txt файл
#cmake
cmake_minimum_required(VERSION 3.5)
project(concentration)
option(set_clang "set clang as default compiler" 0) option(set_gpp "set g++ as default compiler" 0) option(cros_compile "cros compile for win32" 0)
if(${UNIX}) message(STATUS "Unix system") elseif(${WIN32}) message(WARNING "Work is not guaranted") else() message(FATAL_ERROR "System not supported") endif()
if(set_gpp) set(CMAKE_CXX_COMPILER g++) endif() if(set_clang) set(CMAKE_CXX_COMPILER clang++) endif() if(cros_compile) set(PROJECT_NAME ${PROJECT_NAME}.exe) set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++-posix) set(CMAKE_CXX_FLAGS "-static-libstdc++ -static-libgcc") endif()
message(STATUS "Project " ${PROJECT_NAME}) message(STATUS "cxx compiler " ${CMAKE_CXX_COMPILER})
add_definitions(-Wall -std=c++14)
include_directories(include)
set(MAIN_SRC sources/main.cpp) file(GLOB CONCENTRATION_SRC "sources/concentration/*.cpp")
if(cros_compile) find_package(PDCurses REQUIRED) else() find_package(Curses REQUIRED) endif()
include_directories(${CURSES_INCLUDE_DIR})
add_executable(${PROJECT_NAME} ${MAIN_SRC} ${CONCENTRATION_SRC})
target_link_libraries(${PROJECT_NAME} ${CURSES_LIBRARIES})
в общем когда запускаю командами
cmake cmake -Dset_gpp=1
CMake пишет:
-- The C compiler identification is unknown -- The CXX compiler identification is unknown CMake Error at CMakeLists.txt:5 (project): The CMAKE_C_COMPILER:
cl
is not a full path and was not found in the PATH.
To use the NMake generator with Visual C++, cmake must be run from a shell that can use the compiler cl from the command line. This environment is unable to invoke the cl compiler. To fix this problem, run cmake from the Visual Studio Command Prompt (vcvarsall.bat).
Tell CMake where to find the compiler by setting either the environment variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to the compiler, or to the compiler name if it is in the PATH.
CMake Error at CMakeLists.txt:5 (project): The CMAKE_CXX_COMPILER:
cl
is not a full path and was not found in the PATH.
To use the NMake generator with Visual C++, cmake must be run from a shell that can use the compiler cl from the command line. This environment is unable to invoke the cl compiler. To fix this problem, run cmake from the Visual Studio Command Prompt (vcvarsall.bat).
Tell CMake where to find the compiler by setting either the environment variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path to the compiler, or to the compiler name if it is in the PATH.
-- Configuring incomplete, errors occurred! See also "../CMakeFiles/CMakeOutput.log". See also "../CMakeFiles/CMakeError.log".
Путь к компилятору есть в path. g++ команда работает. Постоянно компилирую с командной строки. Пробовал в CmakeLists.txt указывать явный путь к g++. Все равно не помогает. Все пути к файлам - латиница.
В общем, нужна помощь!


Ответ

В Windows, судя по исходникам, CMake по дефолту (если генератор не указан явно) пробует найти (по записям в реестре) самую свежую версию Visual Studio, а если не находит, использует NMake.
Таким образом, если у вас установлена Студия (или просто остался мусор в реестре, в результате некорректного удаления студии или по другим, гораздо более серьезным причинам), то CMake будет делать проект под самую свежую из установленных Студий.
Чтобы явно указать нужный вам генератор, используйте ключик -G:
cmake -G "MinGW Makefiles"

вторник, 5 февраля 2019 г.

Как подружить wxWidgets и CLion (Windows + mingw-w64)?

Хочу сделать GUI приложение и выбрал для этого Си (без ++) и wxWidgets. Скачал с офф.сайта установщик, поставил (Установился в C:\wxWidgets-3.1.1, но я кинул рядом с исходниками папку с библиотекой в папке wx есть файл, который просится в коде).

Думал, что на этом всё, но нет, при попытке компиляции вылазит ошибка, что нет библиотеки.
Ошибка:
"C:\Program Files\JetBrains\CLion 2018.1.5\bin\cmake\bin\cmake.exe" --build C:\Users\Timoshka-WIN10\Documents\CLionProjects\GuiTEST\cmake-build-debug --target GuiTEST -- -j 1 [ 50%] Building C object CMakeFiles/GuiTEST.dir/main.c.obj C:\Users\Timoshka-WIN10\Documents\CLionProjects\GuiTEST\main.c:3:10: fatal error: wx/wxprec.h: No such file or directory #include ^~~~~~~~~~~~~ compilation terminated. mingw32-make.exe[3]: * [CMakeFiles\GuiTEST.dir\build.make:62: CMakeFiles/GuiTEST.dir/main.c.obj] Error 1 mingw32-make.exe2: [CMakeFiles\Makefile2:67: CMakeFiles/GuiTEST.dir/all] Error 2 mingw32-make.exe1: [CMakeFiles\Makefile2:79: CMakeFiles/GuiTEST.dir/rule] Error 2 mingw32-make.exe: * [Makefile:117: GuiTEST] Error 2
CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(GuiTEST C)
set(CMAKE_C_STANDARD 11)
add_executable(GuiTEST main.c)
target_include_directories ( GuiTEST PUBLIC $< BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}libs/wxWidgets-3.1.1/include > $< INSTALL_INTERFACE:libs/wxWidgets-3.1.1/include > # /include/mylib )
Код с офф.сайта wxWidgets
// wxWidgets "Hello World" Program // For compilers that support precompilation, includes "wx/wx.h". #include #ifndef WX_PRECOMP #include #endif class MyApp : public wxApp { public: virtual bool OnInit(); }; class MyFrame : public wxFrame { public: MyFrame(); private: void OnHello(wxCommandEvent& event); void OnExit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); }; enum { ID_Hello = 1 }; wxIMPLEMENT_APP(MyApp); bool MyApp::OnInit() { MyFrame *frame = new MyFrame(); frame->Show(true); return true; } MyFrame::MyFrame() : wxFrame(NULL, wxID_ANY, "Hello World") { wxMenu *menuFile = new wxMenu; menuFile->Append(ID_Hello, "&Hello...\tCtrl-H", "Help string shown in status bar for this menu item"); menuFile->AppendSeparator(); menuFile->Append(wxID_EXIT); wxMenu *menuHelp = new wxMenu; menuHelp->Append(wxID_ABOUT); wxMenuBar *menuBar = new wxMenuBar; menuBar->Append(menuFile, "&File"); menuBar->Append(menuHelp, "&Help"); SetMenuBar( menuBar ); CreateStatusBar(); SetStatusText("Welcome to wxWidgets!"); Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello); Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT); Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT); } void MyFrame::OnExit(wxCommandEvent& event) { Close(true); } void MyFrame::OnAbout(wxCommandEvent& event) { wxMessageBox("This is a wxWidgets Hello World example", "About Hello World", wxOK | wxICON_INFORMATION); } void MyFrame::OnHello(wxCommandEvent& event) { wxLogMessage("Hello world from wxWidgets!"); }
Говорят, что надо что-то подшаманить в CMakeLists.txt, или добавить target_include_directories, но в первом случае вроде под Ubuntu и не понятно, а во втором и по официальному мануалу для CMake тоже ничего не понятно :).


Ответ

target_include_directories( GuiTEST PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libs/wxWidgets-3.1.1/include

среда, 31 октября 2018 г.

Как находить библиотеки с помощью CMake?

У меня в проекте используются библиотеки Boost и WebRTC. При попытке собрать проект возникает проблема со сборкой WebRTC вот скриншот.
CMakeLists.cmake:
cmake_minimum_required(VERSION 3.9)
project(webrtc-server)
if(EXISTS "${CMAKE_SOURCE_DIR}/LocalConfig.cmake") include(LocalConfig.cmake) else() message(FATAL_ERROR "Local config is absent") endif()
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
set (Boost_USE_MULTITHREADED ON) set (Boost_USE_STATIC_LIBS ON) set (Boost_USE_STATIC_RUNTIME OFF) set (BOOST_ALL_DYN_LINK OFF)
include(CMake/CMakeFindExtensions.cmake) include(CMake/CMakeHelpers.cmake) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
find_package(Boost 1.65.1 REQUIRED COMPONENTS program_options system) find_package(WebRTC REQUIRED)
include_directories(${Boost_INCLUDE_DIR}) include_directories(${WEBRTC_INCLUDE_DIR})
message(SOURSE " ${Boost_LIBRARIES}") message(SOURSE " ${Boost_INCLUDE_DIRS}")
if(Boost_FOUND) add_executable(webrtc-server src/webrtc_server.cpp src/webrtc_observers.h ) target_link_libraries(webrtc-server ${Boost_LIBRARIES} ${WEBRTC_LIBRARIES} ) endif()
LocalConfig.cmake:
set(BOOST_ROOT ExternalLibs/boost_1_65_1) set(WEBRTC_ROOT_DIR ExternalLibs/WebRTC)
Tree :
. ├── CMake │   ├── CMakeFindExtensions.cmake │   ├── CMakeHelpers.cmake │   └── FindWebRTC.cmake ├── CMakeLists.txt ├── ExternalLibs │   ├── boost_1_65_1 │   └── WebRTC ├── LocalConfig.cmake ├── README.md ├── scripts │   ├── install_boost.sh │   └── install_webrtc.sh ├── src │   ├── webrtc_observers.h │   └── webrtc_server.cpp └── temp
P.S. В шапке верная версия. Советую внимательно смотреть на регистр переменных - имеет очень важное значение.


Ответ

Поиск библиотек в CMake происходит с использованием базовых команд самого CMake, для поиска по файловой системе. Это такие команды как: find_path, find_library и т.д. Обычному пользователю, как правило, эти команды не нужны, потому что уже кто-то заранее написал скрипт CMake, состоящий из этих команд, который находит всю необходимую информацию по библиотеке/фреймворку.
Обычно такие скрипты имеют вид FindXXX.cmake, где XXX это имя библиотеки. Эти скрипты используются тогда, когда пользователь в своём CMake скрипте использует команду find_package. К примеру, find_package(Boost REQUIRED) ожидает найти файл FindBoost.cmake и когда находит его, то исполняет всё, что находится внутри этого файла.
CMake поставляется с целым набором таких файлов, которые можно найти в директории, где он установлен: share/cmake-xxx/Modules. Имея это список файлов мы можем посмотреть, что за библиотеки поддерживаются CMake из коробки, а также посмотреть, что могут потребовать соответствующие скрипты на вход, чтобы помочь найти ту или иную библиотеку.
Итак, мы перешили в эту директорию и нашли FindBoost.cmake. Благо этот скрипт имеет неплохую документацию, и из него мы сразу узнаём, что для помощи в нахождении boost, ему необходимо знать где находится папка с оным. Для этого он ждёт переменную BOOST_ROOT. Эта переменная может быть установлена как локально в скрипте CMake, так и глобально, как переменная окружения.
Т.е. для того, чтобы нам найти boost, мы можем написать следующее:
set(BOOST_ROOT /home/koshachok/proj/ExternalLibs/Boost_1_65_1) find_package(Boost REQUIRED COMPONENTS program_options system)
Но явно прописывать путь в общем файле это неправильно, лучше используйте переменную окружения или же некоторый обходной путь, который я опишу дополнительно позже.
Заметьте, что каждый скрипт уникален и то, что ожидает скрипт для boost, может отличаться от того, что требует другая библиотека. Поэтому всегда нужно смотреть документацию к скрипту, чтобы понять, чего он от тебя хочет. Если у скрипта хорошая документация, то всё сразу будет понятно. Если нет, тогда придётся из его содержимого понять самостоятельно, чего же он хочет (обычно это не так сложно).
Вооружившись всем вышеописанным идём искать FindWebRTC.cmake в директории CMake и не находим его. Что делать? Первым делом вбиваем в Яндекс FindWebRTC.cmake и, как правило, находим немало вариантов уже готового файла, один из котороых можно выбрать под свои нужды. Я взял первый попавшийся, и он ожидает установленной WEBRTC_ROOT_DIR в качестве помощи в поиске. Но как нам использовать этот файл, как сделать так, чтобы find_package его использовал? Очень просто: помещаем его в дерево исходников, скажем в 3rdParty/cmake. После чего добавляем в наш скрипт (до find_package) такую строку:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/3rdParty/cmake")
После чего, скрипт должен находиться и выполняться. Нам же остаётся использовать его результаты (WEBRTC_INCLUDE_DIR, WEBRTC_LIBRARIES).

Пару слов хочется сказать по поводу того, как и где прописывать полные пути к директориям библиотек, которые помогают скриптам в поиске. Для этого я использую следующий механизм. В основном скрипте CMake добавляем такой код:
if(EXISTS "${CMAKE_SOURCE_DIR}/LocalConfig.cmake") include(LocalConfig.cmake) else() message(FATAL_ERROR "Local config is absent") endif()
После чего добавляем файл LocalConfig.cmake со следующим содержимым:
set(BOOST_ROOT /home/koshachok/proj/ExternalLibs/Boost_1_65_1) set(WEBRTC_ROOT_DIR /home/koshachok/proj/ExternalLibs/WebRTC)
И, собственно, всё. Каждый разработчик просто создаёт свой локальный конфиг, который никак не мешает основному файлу CMake.