после некоторого исследования у меня теперь есть собственная версия самого простого, но полного примера cmake. Вот он, и он пытается охватить большинство основ, включая ресурсы и упаковку.
одна вещь, которую он выполняет нестандартно, - это обработка ресурсов. По умолчанию cmake хочет поместить их в / usr / share /, / usr / local / share / и что-то подобное в Windows. Я хотел иметь простой zip / tar.gz, который можно было распаковать где угодно и запустить. Поэтому ресурсы загружаются относительно исполняемого файла.
Основное правило для понимания команд cmake - это следующий синтаксис:
<function-name>(<arg1> [<arg2> ...])
без запятой и точки с запятой. Каждый аргумент представляет собой строку. foobar(3.0)
и foobar("3.0")
то же самое. вы можете установить списки / переменные с помощью set(args arg1 arg2)
. С этим набором переменных foobar(${args})
и foobar(arg1 arg2)
фактически то же самое. Несуществующая переменная эквивалентна пустому списку. Список внутри представляет собой просто строку с точкой с запятой для разделения элементов. Таким образом, список с одним элементом по определению является именно этим элементом, без упаковки. Переменные глобальные. Встроенные функции предлагают некоторую форму именованных аргументов , поскольку они ожидают некоторых идентификаторов, таких как PUBLIC
илиDESTINATION
в их списке аргументов, чтобы сгруппировать аргументы. Но это не языковая функция, эти идентификаторы также являются просто строками и анализируются реализацией функции.
вы можете клонировать все с github
cmake_minimum_required(VERSION 3.0)
project(example_project)
###############################################################################
## file globbing ##############################################################
###############################################################################
# these instructions search the directory tree when cmake is
# invoked and put all files that match the pattern in the variables
# `sources` and `data`
file(GLOB_RECURSE sources src/main/*.cpp src/main/*.h)
file(GLOB_RECURSE sources_test src/test/*.cpp)
file(GLOB_RECURSE data resources/*)
# you can use set(sources src/main.cpp) etc if you don't want to
# use globing to find files automatically
###############################################################################
## target definitions #########################################################
###############################################################################
# add the data to the target, so it becomes visible in some IDE
add_executable(example ${sources} ${data})
# just for example add some compiler flags
target_compile_options(example PUBLIC -std=c++1y -Wall -Wfloat-conversion)
# this lets me include files relative to the root src dir with a <> pair
target_include_directories(example PUBLIC src/main)
# this copies all resource files in the build directory
# we need this, because we want to work with paths relative to the executable
file(COPY ${data} DESTINATION resources)
###############################################################################
## dependencies ###############################################################
###############################################################################
# this defines the variables Boost_LIBRARIES that contain all library names
# that we need to link to
find_package(Boost 1.36.0 COMPONENTS filesystem system REQUIRED)
target_link_libraries(example PUBLIC
${Boost_LIBRARIES}
# here you can add any library dependencies
)
###############################################################################
## testing ####################################################################
###############################################################################
# this is for our testing framework
# we don't add REQUIRED because it's just for testing
find_package(GTest)
if(GTEST_FOUND)
add_executable(unit_tests ${sources_test} ${sources})
# we add this define to prevent collision with the main
# this might be better solved by not adding the source with the main to the
# testing target
target_compile_definitions(unit_tests PUBLIC UNIT_TESTS)
# this allows us to use our executable as a link library
# therefore we can inherit all compiler options and library dependencies
set_target_properties(example PROPERTIES ENABLE_EXPORTS on)
target_link_libraries(unit_tests PUBLIC
${GTEST_BOTH_LIBRARIES}
example
)
target_include_directories(unit_tests PUBLIC
${GTEST_INCLUDE_DIRS} # doesn't do anything on Linux
)
endif()
###############################################################################
## packaging ##################################################################
###############################################################################
# all install commands get the same destination. this allows us to use paths
# relative to the executable.
install(TARGETS example DESTINATION example_destination)
# this is basically a repeat of the file copy instruction that copies the
# resources in the build directory, but here we tell cmake that we want it
# in the package
install(DIRECTORY resources DESTINATION example_destination)
# now comes everything we need, to create a package
# there are a lot more variables you can set, and some
# you need to set for some package types, but we want to
# be minimal here
set(CPACK_PACKAGE_NAME "MyExample")
set(CPACK_PACKAGE_VERSION "1.0.0")
# we don't want to split our program up into several things
set(CPACK_MONOLITHIC_INSTALL 1)
# This must be last
include(CPack)
For example I don't want to update my CMakeList.txt when I am adding a new folder in my src tree
вы можете привести пример IDE, которая автоматически собирает исходники?