LINUX.ORG.RU

Cmake, mingw32 и сборка под Ubuntu для получения exe-файла

 


0

2

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

x86_64-w64-mingw32-c++  sailboat.c  -o sailboat.exe  -lglfw3dll -lglfw3 -static-libgcc -static-libstdc++  -lopengl32  -Wl,--subsystem,windows
На выходе получаем exe-шник, который запускается под Windows (или Wine).

Однако, если использовать CMake:

cmake_minimum_required(VERSION 3.0)	# Проверка версии CMake.
					

set (PROJECT sailboat) 		        # Название проекта
project(${PROJECT})

set(OpenGL_GL_PREFERENCE LEGACY)
find_package(OpenGL REQUIRED)
find_package(glfw3  REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})


find_library(PTHREAD_LIB pthread)

                                   # Установка переменной со списком исходников для исполняемого файла
#set (SOURCES  gl_core_4_3.c)
#set (HEADERS  gl_core_4_3.h)
set (LIBS ${LIBS} ${OPENGL_LIBRARY} ${GLFW_LIBRARIES} )


set (MINGW=ON)
set (CMAKE_SYSTEM_NAME=Windows)
#set_target_properties (${PROJECT} PROPERTIES CMAKE_WIN32_EXECUTABLE True)

set( CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "" )
set( CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "" )

set (BUILD_SHARED_LIBS=OFF)
set (BUILD_CLAR=OFF)
set (THREADSAFE=ON)

set (CMAKE_C_COMPILER   /usr/bin/x86_64-w64-mingw32-c++)
set (CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-c++)

set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -static")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")

set(CMAKE_LIBRARY_PATH /usr/x86_64-w64-mingw32/lib)

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_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--subsystem,windows")


add_executable (${PROJECT} WIN32 ${HEADERS} ${SOURCES} sailboat.c)    # Создает исполняемый файл с именем PROJECT

set_target_properties (${PROJECT} PROPERTIES LINK_FLAGS_DEBUG   "/SUBSYSTEM:windows")
set_target_properties (${PROJECT} PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:windows")       

#set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++ -lglfw3dll")

target_include_directories(${PROJECT} PUBLIC
                           $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
                           $<INSTALL_INTERFACE:include>)


				  # Линковка программы с библиотеками
#target_link_libraries( PUBLIC glfw  ${PTHREAD_LIB} )
target_link_libraries(${PROJECT} PUBLIC ${OPENGL_gl_LIBRARY} glfw)
то происходит такая вещь:

[ 50%] Linking C executable sailboat
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lGL
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lrt
/usr/bin/x86_64-w64-mingw32-ld: cannot find -ldl
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lX11
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/sailboat.dir/build.make:89: sailboat] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/sailboat.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Вообще-то линкер не должен требовать этих библиотек для сборки для Windows. В чем причина?

PS Извините, я новичок в CMake, поэтому CMakeLists.txt такой сумбурный.


Я думаю правильно тебе почитать вот эту страницу: https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html

То есть указать что ты хочешь компилировать под Windows, а не под Linux самостоятельно создав файл тулчейна

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Windows)

# which compilers to use for C and C++
set(CMAKE_C_COMPILER   i586-mingw32msvc-gcc)
set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++)

# where is the target environment located
set(CMAKE_FIND_ROOT_PATH  /usr/i586-mingw32msvc
    /home/alex/mingw-install)

# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 2)
Ответ на: удаленный комментарий

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

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

Переставь тогда переменные которые задаются обычно в тулчейн файле в начало.

То есть как минимум выше чем

find_package(OpenGL REQUIRED)
find_package(glfw3  REQUIRED)
fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от fsb4000

Проблемы не в этих OpenGL и glfw3 библиотеках. Они нормально видятся и линкуются. CMake не до конца понимает, что мне нужна сборка для Windows и лепит в выходной make-файл библиотеку linux

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

Эти библиотеки установлены в систему? Проблема может быть и в них: если файл toolchain написан не совсем корректно, cmake может в find_package найти и потом пытаться использовать библиотеки для linux.

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

Отдельным не пробовал, т.к. тогда придется жутко перегрузить командную строку cmake, т.е. писать cmake -Dxxx -Dyyy(когда можно эти xxx,yyy загнать в CMakeList.txt). Хотя вообще можно попробовать сделать отдельный тулчейн, но сейчас времени нету на это.

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

Библиотеки (линукстовые, те что с префиксом -l), конечно установлены. Собираю исполнимый (для Linux) g++-компилятором c ними без проблем. Только там естественно другие ключи компиляции, чем для mingw32/

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

Я бы начал с минималистичного сборочного скрипта, который собирает приложение для Linux, затем добавил toolchain для windows с нужными флагами. И это было бы быстрее.

cmake_minimum_required(VERSION 3.0)	# Проверка версии CMake.
					

set (PROJECT sailboat) 		        # Название проекта
project(${PROJECT})

set(OpenGL_GL_PREFERENCE LEGACY)
find_package(OpenGL REQUIRED)
find_package(glfw3  REQUIRED)

# Установка переменной со списком исходников для исполняемого файла
#set (SOURCES  gl_core_4_3.c)
#set (HEADERS  gl_core_4_3.h)
# Создает исполняемый файл с именем PROJECT
add_executable (${PROJECT} ${HEADERS} ${SOURCES} sailboat.c)

# Линковка программы с библиотеками
target_link_libraries(${PROJECT} PUBLIC OpenGL::GL glfw)
DrBrown
()

Однако, если использовать CMake:

Вывод: не нужно использовать CMake там, где у тебя проект собирается куда проще и быстрее тремя строками в Makefile. Что это за адовая простыня которую ты тут опубликовал? Это действительно подходящяя система сборки для приложения-кнопки?

PS Извините, я новичок в CMake, поэтому CMakeLists.txt такой сумбурный.

Всё просто: выброси CMake. Неудобная и откровенно паршивая сборочная система. Вот ты уже битый час ковыряешься с этим говном, а мог забить и вместо этого писать полезный код, получать удовольствие.

А так даже если ты решишь эту задачу тебя ждёт убогая портянка в которой строк будет больше чем в твоём исходнике. Рука-то поднимется закоммитить эту дрянь в репозиторий и удалить аккуратный и лаконичный Makefile со строчкой x86_64-w64-mingw32-c++ sailboat.c -o sailboat.exe -lglfw3dll -lglfw3 -static-libgcc -static-libstdc++ -lopengl32 -Wl,--subsystem,windows в которой всё просто и понятно?

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

Думаю, cmake был выбран из-за возможности сборки приложения на разных платформах. И тут у тебя есть прекрасная возможность продвижения meson – покажи на практике как он прекрасен в этой ситуации.

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

Прекрасным в случае ТС будет нечто вроде:

SOURCES=sailboat.c

all: linux

linux:
	c++ $(SOURCES) -o sailboat -lglfw3 -lOpenGL

windows:
	x86_64-w64-mingw32-c++ -static-libgcc -static-libstdc++ $(SOURCES) -o sailboat.exe \
		-lglfw3dll -lglfw3 -lopengl32 -Wl,--subsystem,windows

macos:
	clang++ $(SOURCES) -o sailboat -lglfw3 -framework Cocoa -framework OpenGL -framework IOKit

Вместо всех тех идиотских CMake-портянок в которых он ковыряется вот уже 3 часа.

EXL ★★★★★
()

Зачем нужны все эти subsystem:windows, если уже указано add_executable(WIN32)?

set (PROJECT sailboat)
project(${PROJECT})

даже это не нужно, project(sailboat) само по себе задает переменную ${PROJECT_NAME} с именем проекта.

Свойства должны задаваться для таргетов, а не глобально. И уж тем более не надо трогать CMAKE_C{XX}_FLAGS.

Макросы с BUILD_INTERFACE и INSTALL_INTERFACE нужны для устанавливаемых библиотек, а не для экзешников. Зачем они тут?

Тулчейн - это вещь, которая задается отдельно, а не хардкодится. В чем вообще проблема написать -DCMAKE_TOOLCHAIN_FILE=... в консоли? Можно использовать cmake-gui, если консоль так коробит.

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

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

Я согласен, что CMake неудобен. Удивительно, что он такой популярный (наверное за цветной вывод). Может только поэтому надо хоть немного разбираться в нем.

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

Это скрипт собирающий среду для кроскомпиляции в венду. Умеет пакеты ставить и вообще няшный. Смысл в том что с ним можно будет без шамаства собрать обычный cmake проект, он сам найдёт нужный компилятор и зависимости. Я так и делаю. Очень удобно.

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

Спасибо EXL! Это самый лучший вариант! Только у меня так компилируется:

SOURCES=sailboat.c

all: linux

linux:
	g++ -pthread  $(SOURCES) -o sailboat -L/usr/local/lib -lpthread -lglfw3 -ldl -lm -lGL -lGLU -lX11

windows:
	x86_64-w64-mingw32-c++ -static-libgcc -static-libstdc++ $(SOURCES) -o sailboat.exe \
		-lglfw3dll -lglfw3 -lopengl32 -Wl,--subsystem,windows
clean:
	rm -rf *.o sailboat sailboat.exe            

А вот и сам sailboat: https://i.postimg.cc/HkjyNL2V/sailboat.png

https://webhamster.ru/mytetrashare/index/mtb0/15127372706wu473pm71

... Дело в том, что в Makefile прописаны команды, которые в момент запуска команды make вызвают программу cmake и которая в свою очередь будет парсить CMakeLists.txt!

То есть, файл Makefile, сгенерированный CMake - он, по сути, неполноценный. И без файла CMakeLists.txt, и без установленной в системе cmake, программу из такого Makefile невозможно будет собрать.

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

То есть, файл Makefile, сгенерированный CMake - он, по сути, неполноценный. И без файла CMakeLists.txt, и без установленной в системе cmake, программу из такого Makefile невозможно будет собрать.

Вместо откровений от @Xintrea лучше читать документацию.

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

Тулчейн:

# Sample toolchain file for building for Windows from an Ubuntu Linux system.
#
# Typical usage:
#    *) install cross compiler: `sudo apt-get install mingw-w64`
#    *) cd build
#    *) cmake -DCMAKE_TOOLCHAIN_FILE=~/mingw-w64-x86_64.cmake ..
# This is free and unencumbered software released into the public domain.

set (CMAKE_SYSTEM_NAME Windows)
set (TOOLCHAIN_PREFIX x86_64-w64-mingw32)

# cross compilers to use for C, C++
set (CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set (CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set (CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)

# target environment on the build host system
set (CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})

# modify default behavior of FIND_XXX() commands
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# @matheusdiogenesandrade
 
Makelist.txt
cmake_minimum_required(VERSION 3.0)	# Проверка версии CMake.
					

set (PROJECT sailboat) 		        # Название проекта
project(${PROJECT})

set (OpenGL_GL_PREFERENCE LEGACY)
find_package (OpenGL REQUIRED)
find_package (glfw3  REQUIRED)
                                        # Для Linux
#set (CMAKE_C_COMPILER    /usr/bin/gcc) 
#set (CMAKE_CXX_COMPILER  /usr/bin/g++)
                                       

# Установка переменных со списком исходников для исполняемого файла
#set (SOURCES  gl_core_4_3.c)
#set (HEADERS  gl_core_4_3.h)

# Создает исполняемый файл с именем PROJECT
                                           # Для Linux
#add_executable (${PROJECT} ${HEADERS} ${SOURCES} sailboat.cpp)
                                           # Для Windows
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
set (CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
add_executable (${PROJECT} WIN32 ${HEADERS} ${SOURCES} sailboat.cpp)

# Линковка программы с библиотеками
target_link_libraries (${PROJECT} PUBLIC OpenGL::GL glfw)
 

Вывод:

[ 50%] Building CXX object CMakeFiles/sailboat.dir/sailboat.cpp.obj
[100%] Linking C executable sailboat.exe
/usr/bin/x86_64-w64-mingw32-ld: attempted static link of dynamic object `/usr/lib/x86_64-linux-gnu/librt.so'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/sailboat.dir/build.make:91: sailboat.exe] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/sailboat.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

 
Все равно CMake не врубается, что виндовые библитеки надо брать, а не линуксовые.

Gyros
() автор топика