Перейти к содержимому

Cmake как подключить библиотеку

  • автор:

Как подключить библиотеку к Cmake?

Я всегда писал код в visual studio совершенно не парясь ни о чём, но теперь я пытаюсь написать небольшую программку, которая будет работать как на windows, так и на linux. Хорошо, я создал проект Cmake, теперь мне нужно подключить библиотеки (glm, glfw, sockpp) Glm и glfw я подключил, просто скопировав репозиторий из гитхаба и прописав в cmakelists.txt
add_subdirecory([путь до папки])
target_link_libraries(myproject [название библиотеки из её cmakelists]) Но с sockpp возникла проблема, при сборке компилятор пишет Ошибка LNK1104 не удается открыть файл «sockpp.lib»
При этом проект нормально собирается утилитой Cmake gui, но он выплевывает проект visual studio, а мне нужна кроссплатформенность. Правильно ли я подключаю библиотеки к своему проекту? Как их нужно подключать? Если я хочу подключить библиотеку, которая не содержит cmakelists.txt, а только makefile, (например asio) то как быть? Есть ли пути написания кроссплатформенных программ без Cmake?

Отслеживать

задан 19 июн 2021 в 10:38

1 1 1 бронзовый знак

Тут слишком много вопросов в одном вопросе. Cmake для написания кроссплатформенных программ не нужен вообще. Зато нужен тулсет для кросс компиляции или машина нативным тулсетом для целевой платформы. А подключать разные библиотеки на разных платформах в cmake придется очень по-разному.

Что это и зачем нужно

CMake — кроссплатформенная автоматизированная система сборки проектов. Непосредственно сборкой она не занимается, а только генерирует Makefile, который потом будет выполнен утилитой make.

CMake может проверять наличие необходимых библиотек и подключать их, собирать проекты под разными компиляторами и операционными системами. Т.е. у вас есть куча кода и файлик, содержащий информацию для cmake, и чтобы скомпилить это дело где-нибудь еще, вам нужно просто запустить там cmake, который сделает всё сам. Удобно, полезно, просто.

Краткое описание

Если нет желания/времени/сил читать весь туториал и Вы используете какой-нибудь QtCreator (или любая другая IDE, умеющая работать с cmake), то:

  • Создайте в IDE проект под cmake
  • Найдите в папке с проектом CMakeFiles.txt
  • Пробегитесь глазами по туториалу, соотнося его с вашим CMakeFiles.txt

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

Старт

Предполагается, что найти и скачать сам cmake ты, %username%, в состоянии. //а если нет?

Предположим, у Вас есть исходничек «test.cpp» (// а если нет?)(А если нет, то CMake тебе трогать рано). Для начала нужно создать файлик для cmake, который обычно называют «CMakeLists.txt», и написать туда вот это:

add_executable(test test.cpp)

Теперь запускаем (из консоли) в этой папке команду «cmake CMakeLists.txt» (аргументом можно передавать не только файл, но и директорию, в которой он лежит, тогда cmake найдет его сам).

cmake будет использовать переданный (или найденный) файл проекта (тот самый CMakeLists.txt), и в текущей директории будет создавать проект. Проект — это много-много файлов и директорий (примечание: поэтому лучше запускать cmake из другой директории, чтобы можно было, например, быстро удалить все бинарники), из которых нас больше всего интересует Makefile.

Makefile — это файл, нужный для утилиты make. Именно она запускает компиляторы, линковщики и прочие радости. Запускаем make в каталоге сборки (т.е. там же, где Вы запускали cmake). В консоли вылезет примерно такой текст:

Scanning dependencies of target test [100%] Building CXX object CMakeFiles/test.dir/test.cpp.o Linking CXX executable test [100%] Built target test

А у Вас в папочке появится исполняемый файл «test». Запустите, убедитесь, что это действительно то, что ожидается от компиляции файла «test.cpp».

Подробное описание

Поразбираемся с различными возможностями cmake.

Указание необходимой версии cmake

cmake_minimum_required(VERSION 2.6)

Указывайте высокую минимальную версию CMake. Если используемая версия cmake меньше 2.6, он не захочет работать. Писать эту команду всегда — хороший стиль (cmake будет пыхтеть и обижаться, если вы не укажете версию, но собирать всё равно всё будет).

Название проекта

project(visualization)

Указывает, что этот cmake-файл является корневым для некоторого проекта. С проектами связаны определенные переменные и поведение cmake (читайте документацию).

Переменные

В cmake можно создавать текстовые переменные. Команда

set(VARIABLE The variable's value)

запишет в переменную «VARIABLE» значение «The variable’s value». Чтобы где-либо использовать значение этой переменной, нужно написать $.

Чтобы добавить к переменной некий текст, можно сделать так:

set(VARIABLE "$ new text")

Как видите, использовать значение можно и внутри кавычек. Переменные активно используются различными библиотеками — для установки флагов, параметров сборки/линковки и прочих вкусностей, об этом чуть-чуть попозже.

Пример коше’гного проекта со списком сорцов в отдельной переменной:

cmake_minimum_required(VERSION 2.6) set(SOURCES test.cpp lib1.cpp lib2.cpp) add_executable(test $)

Устанавливаем команды компилятору

add_definitions(-DSOME_IMPORTANT_DEFINITION)

Эта команда используется для установки дефайнов, которыe можно проверить в коде через, например, #ifdef SOME_IMPORTANT_DEFINITION.

set(CMAKE_CXX_FLAGS "$ -std=c++11 -Wall")

Эта команда добавит к флагам, используемым при сборке c++-кода, флаги -std=c++11 и -Wall.

Кто не знает: «-std=c++11» включает в gcc поддержку стандарта c++11, «-Wall» говорит gcc выводить все предупреждения (очень советую, помогает отловить много глупых багов и писать аккуратный код).

Если ваша версия GCC меньше, чем 4.7.0, вместо -std=c++11 нужно использовать -std=c++0x.

В GCC 4.8.0 появился флаг -std=c++1y, в котором начинают реализовывать фичи следующего стандарта.

Папка с хедерами

Допустим, Вы хотите, чтобы хедеры (файлики, подключаемые через #include) искались еще и в каталогах «headers/» и «more_headers/»:

include_directories("headers/" "more_headers/")

Надеюсь, и это понятно.

Самое важное — подключение библиотек

Научимся искать и подключать библиотеки при помощи cmake на примере Boost. Для начала установим переменные для буста:

set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED ON)

Первое — мы не хотим, чтобы буст подключался к нам статически (т.е. хотим динамическую линковку). Если ты, %username%, не знаешь, что это, пока просто забей и используй этот флаг так, как написано. Но в ближайшее время узнай, о чем речь. Второй флаг разрешает бусту внутри своих магических реализаций использовать треды для распараллеливания и прочих радостей.

Итак, мы установили флаги. Давайте найдем буст!

Допустим, нам нужны компоненты буста под названием chrono (библиотека для работы со временем) и filesystem (библиотека для работы с файловой системой):

find_package(Boost COMPONENTS chrono filesystem REQUIRED)

Win, будут искаться только нужные библиотеки, и их расположение будет записано в переменную Boost_LIBRARIES.

Опция «REQUIRED» говорит о том, что библиотека необходима проекту. Без нее cmake решит, что отсутствие данной библиотеки — не так уж и страшно, и будет собирать дальше.

Добавим директории с хедерами буста для поиска в них хедеров:

include_directories($)

Итак, осталось найденные библиотеки подключить к исполняемому файлу.

target_link_libraries(test $)

В качестве библиотек нужно указать пути к необходимым собранным библиотекам. cmake нашел указанные нами библиотеки и записал в переменную, чем мы и пользуемся.

Заметим, что эту команду нужно вызывать после того, как создан target сборки (через add_executable).

Пример хорошего CMakeLists.txt и где он будет лежать

Итак, полный пример использования всего этого. У нас есть некая директория (отныне считаем ее «/sources»), и в ней лежат исходники

/sources/lib1/main.cpp /sources/lib2/main.cpp /sources/main.cpp

В корне «/» лежит файл «/CMakeLists.txt»:

cmake_minimum_required(VERSION 2.8) project(cmake-example) set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED ON) find_package(Boost COMPONENTS chrono filesystem REQUIRED) set(CMAKE_CXX_FLAGS "$\$$ -std=c++11 -Wall") set(SRC_LIST lib1/main.cpp lib2/main.cpp main.cpp) add_executable($\$$ $\$$) target_link_libraries($\$$ $\$$)

Если Вам что-то в нём не понятно — перечитайте соответствующую информацию выше.

Создаем директорию «/build» (не «/sources/build»), переходим в нее, запускаем в ней «cmake ..». «..» — метка родительской директории. cmake возьмет из нее наш CMakeLists.txt и по нему создаст проект в папке «/build». Чтобы проект собрать, запускаем «make» в той же папке «/build».

Таким образом, в корне у нас есть:

  • CMakeLists.txt
  • директория с исходниками
  • каталог сборки

Все разделено, автоматизировано и удобно.

Как создать библиотеку в поддиректории и слинковать ее с основной программой

Пусть в ./ лежит основной проект, а в ./subdir мы хотим сделать либу, а в ./build построить проект.

project(MegaLibrary) set(SOURCES lib.cpp) set(HEADERS lib.h) add_library(lib $\$$ $\$$) target_include_directories(lib PUBLIC $\$$)
project(MainProject) set(MAIN_PROJECT_SRC_LIST main) # Other stuff
add_executable(main $\$$) add_subdirectory(subdir) target_link_libraries(main lib)

Теперь можно в файлах основного проекта делать #include «lib.h» (см. документацию по target_include_directories).

В ./build запускаем «cmake .. && make» и получаем собранный проект.

Как использовать CMake в связке с QtCreator

Интеграция с cmake у QtCreator не очень тесная, тем не менее, работать с ним можно.

Создаем новый проект без использования Qt, выбираем «Проект на С++ с использованием CMake». Создастся дефолтный файл сборки, который просто добавляет все исходники в директории проекта и компилирует их в один бинарник.

Как добавить header в проект, чтобы его было видно в списке файлов

Если вы создали файл header.h в директорию проекта, просто строчку

add_executable($\$$ $\$$)
add_executable($\$$ $\$$ "header.h")

CMake. Как подключить библиотеку из файла?

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

У меня есть библиотека для представления приближенных чисел, собираемая в статическую библиотеку.

Конфигурация библиотеки

cmake_minimum_required(VERSION 3.19) project(approx_lib) set(CMAKE_CXX_STANDARD 20) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY $/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY $/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $/bin/examples) add_library(approx_lib STATIC include/approx_number.h src/approx_number.cpp) target_include_directories(approx_lib PUBLIC include/) install(TARGETS approx_lib LIBRARY DESTINATION lib)

Как можно заметить по конфигурации, в ней присутствует класс approx_number, разделенный на заголовочный файл approx_number.h и реализацию approx_number.cpp.
После сборки библиотеки производим установку в по пути /usr/local/lib/libapprox_lib.a

Есть приложение, которое библиотеку использует

Конфигурация приложения

cmake_minimum_required(VERSION 3.19) project(just_calculator VERSION 1.0.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) find_library(APPROX_LIB approx_lib HINTS /usr/local/lib REQUIRED) message(STATUS "Found approx_lib: $") add_executable(just_calculator main.cpp) target_link_libraries(just_calculator LINK_PUBLIC $)

После загрузки конфигурации видим, что библиотека нашлась

-- Found approx_lib: /usr/local/lib/libapprox_lib.a -- Configuring done -- Generating done

Для работы приложения нам нужен класс approx_number, а значить надо подключить заголовочный файл approx_number.h из библиотеки.
Прописываем в main.cpp #include

60baa8c8ea456812711705.png

Но получаем сообщение об ошибке:

Так как же подключить библиотеку?

  • Вопрос задан более двух лет назад
  • 2450 просмотров

Комментировать
Решения вопроса 1

Так у вас либа из двух частей — собственно, архив .a, и хедер (или хедеры).

install(TARGETS approx_lib LIBRARY DESTINATION lib) — ставит только собранный target (т.е. непосредственно файл статик либы), но не хедер!

Если не производить установку — можно либу подключить как add_subdirectory с путём к исходникам. Тогда она будет частью основного проекта, будет собираться вместе с ним и всё нужное найдётся (покуда target_include_directories прописан и знает, где искать).

Если устанавливать — то, очевидно, надо установить и хедеры тоже. И ещё как-то сообщить проекту, где что лежит.

Вот кусочек из нашей кастомной сборки icu (пусть имя пакета будет foo, а не icu. А namespace — baz. Так интереснее!)

add_library(icu . ) target_include_directories(icu PUBLIC $/source/common>$) install ( TARGETS icu EXPORT icuExport RUNTIME DESTINATION lib LIBRARY DESTINATION lib ) install ( DIRECTORY source/common/unicode DESTINATION include/icu FILES_MATCHING PATTERN "*.h") # install exports set ( CMAKE_CMAKE_DIR "lib/cmake/foo" ) install ( EXPORT icuExport FILE foo-targets.cmake DESTINATION "$" NAMESPACE baz:: ) file ( WRITE foo-config.cmake "if(NOT TARGET baz::icu) include(\"\$/foo-targets.cmake\") endif()") install ( FILES foo-config.cmake DESTINATION "$" )

Здесь несколько моментов.
Во-первых, обратите внимание на target_include_directories. Там два пути. Один будет работать при сборке, второй — при инсталляции. Т.е. когда собирается либа, либо подключается через add_subdirectory — найдётся нужное по первому пути. После установки — по второму, и этот второй — относительный.

Во-вторых, при установке задано имя export. Это что-то вроде именованного набора разных свойств, которые cmake накапливает из добавленных с этим именем целей и потом может оформить в файл экспорта. В данном случае туда попадает явно прописанная библиотека, и неявно — include-path от неё, последний потому что он изначально включён как public.

В-третьих, собственно, ставим помимо таргета и сами хедеры!

И в-последних, ставим то, что «накопил» экспорт. Первый файл foo-targets.cmake. Второй — который будет работать при поиске пакета (я его осознанно упростил, на самом деле он длиннее) foo-config.cmake.

Всё это куда-то ставится. Например, в /root/bar (для определённости) — как `cmake —install . —prefix /root/bar`. У вас оно прямо в систему, но тут спецом левый путь, чтобы глазами было видно, как он в конфиге пробрасывается и используется.

Потом в самом проекте — не надо никаких find_library, всё же известно, где!

LIST (APPEND CMAKE_PREFIX_PATH "/root/bar") find_package(foo) add_executable(my_prog main.cpp) target_link_libraries(my_prog PRIVATE baz::icu)

find_package сперва пытается найти модуль FindFoo.cmake. Такого нет. Потом пытается найти конфиг FooConfig.cmake или foo-config.cmake. Он разыскивается по указанному префиксу (там весьма развесистый алгоритм, который умеет заглядывать в разные папки, в доках всё есть) и включается. Он, в свою очередь, включает. foo-targets.cmake, сгенерированный из экспорта. И вот там и находится вся магия.

. # это сгенерированный код! # Create imported target baz::icu add_library(baz::icu STATIC IMPORTED) set_target_properties(baz::icu PROPERTIES INTERFACE_COMPILE_DEFINITIONS "U_STATIC_IMPLEMENTATION;U_CHARSET_IS_UTF8=1;U_NO_DEFAULT_INCLUDE_UTF_HEADERS=1" INTERFACE_INCLUDE_DIRECTORIES "$/include/icu" ) . # Load information for each installed configuration. get_filename_component(_DIR "$" PATH) file(GLOB CONFIG_FILES "$/foo-targets-*.cmake") foreach(f $) include($) endforeach() . . а это файл foo-targets-relwithdebinfo.cmake # Import target "baz::icu" for configuration "RelWithDebInfo" set_property(TARGET baz::icu APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO) set_target_properties(baz::icu PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELWITHDEBINFO "CXX" IMPORTED_LOCATION_RELWITHDEBINFO "$/lib/libicu.a" )

а вообще в доках cmake (не надо никаких левых вики/SO!) этой теме посвящён большой и подробный раздел.

Руководство CMake. Шаг 2. Добавление библиотеки

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

Руководство CMake. Шаг 2. Добавление библиотеки

Упражнение 1. Создание библиотеки

Чтобы добавить библиотеку в CMake, используйте команду add_library() и укажите, какие исходные файлы должны составлять эту библиотеку.

Вместо того, чтобы размещать все исходные файлы в одном каталоге, мы можем организовать наш проект с одним или несколькими подкаталогами. В данном случае мы создадим подкаталог специально для нашей библиотеки. В нем мы можем добавить новый файл CMakeLists.txt и один или несколько исходных файлов. В файле CMakeLists.txt верхнего уровня мы будем использовать команду add_subdirectory() , чтобы добавить подкаталог в сборку.

Как только библиотека создана, она подключается к нашей исполняемой цели с помощью команд target_include_directories() и target_link_libraries() .

Цель

Добавить и использовать библиотеку.

Полезные ресурсы

  • add_library()
  • add_subdirectory()
  • target_include_directories()
  • target_link_libraries()
  • PROJECT_SOURCE_DIR

Редактируемые файлы

  • CMakeLists.txt
  • tutorial.cxx
  • MathFunctions/CMakeLists.txt

С чего начать

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

Для этого урока мы поместим библиотеку в подкаталог MathFunctions . Этот каталог уже содержит заголовочный файл MathFunctions.h и исходный файл mysqrt.cxx . Нам не нужно будет изменять ни один из этих файлов. В исходном файле есть одна функция, mysqrt , которая обеспечивает функционал, аналогичный функции sqrt компилятора.

В каталоге Help/guide/tutorial/Step2 начните с TODO 1 и завершите TODO 6.

Сначала добавьте одну строку CMakeLists.txt в подкаталоге MathFunctions .

Затем отредактируйте CMakeLists.txt верхнего уровня.

И в конце используйте недавно созданную библиотеку MathFunctions в tutorial.cxx .

Сборка и запуск

Запустите исполняемый файл cmake или cmake-gui , чтобы настроить проект, а затем собрать его с помощью выбранного инструмента сборки.

Ниже показано, как это выглядит из командной строки:

mkdir Step2_build cd Step2_build cmake ../Step2 cmake --build .

Попробуйте использовать только что собранное приложение Tutorial и убедитесь, что оно по-прежнему выдает точные значения квадратного корня.

Решение

В файле CMakeLists.txt в каталоге MathFunctions мы создаем целевую библиотеку с именем MathFunctions с помощью add_library() . Исходный файл библиотеки передается в качестве аргумента функции add_library() . Это выглядит как следующая строка:

TODO 1

add_library(MathFunctions mysqrt.cxx)

Чтобы использовать новую библиотеку, добавим вызов add_subdirectory() в файл CMakeLists.txt верхнего уровня, чтобы библиотека была собрана.

TODO 2

add_subdirectory(MathFunctions)

Затем новая цель библиотеки связывается с исполняемой целью с помощью target_link_libraries() .

TODO 3

target_link_libraries(Tutorial PUBLIC MathFunctions)

Наконец, нам нужно указать расположение заголовочного файла библиотеки. Измените target_include_directories() , чтобы добавить подкаталог MathFunctions в качестве включаемого каталога, чтобы можно было найти заголовочный файл MathFunctions.h .

TODO 4

target_include_directories(Tutorial PUBLIC "$" "$/MathFunctions" )

Теперь воспользуемся нашей библиотекой. В tutorial.cxx включите MathFunctions.h :

TODO 5

#include "MathFunctions.h"

Наконец, замените вызов sqrt нашей библиотечной функцией mysqrt .

TODO 6

const double outputValue = mysqrt(inputValue);

Упражнение 2. Делаем нашу библиотеку необязательной

Теперь давайте сделаем библиотеку MathFunctions необязательной. Хотя для данного руководства в этом нет необходимости, для больших проектов это обычное дело.

CMake может сделать это с помощью команды option() . Она дает пользователям переменную, которую они могут изменить при конфигурировании своей сборки cmake. Этот параметр будет храниться в кеше, поэтому пользователю не нужно устанавливать значение каждый раз, когда он запускает CMake в каталоге сборки.

Цель

Добавить возможность сборки без MathFunctions .

Полезные ресурсы

Редактируемые файлы

  • CMakeLists.txt
  • tutorial.cxx
  • TutorialConfig.h.in

С чего начать

Начните с файлов, полученных в упражнении 1. Выполните TODO 7TODO 13.

Сначала создайте переменную USE_MYMATH с помощью команды option() в файле CMakeLists.txt верхнего уровня. В том же файле используйте этот параметр, чтобы определить, следует ли создавать и использовать библиотеку MathFunctions .

Затем обновите tutorial.cxx и TutorialConfig.h.in , чтобы использовать USE_MYMATH .

Сборка и запуск

Поскольку наш каталог сборки уже был настроен в упражнении 1, мы можем пересобрать его, просто вызвав следующие команды:

cd ../Step2_build cmake --build .

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

Теперь давайте изменим значение USE_MYMATH на OFF . Самый простой способ – использовать cmake-gui или ccmake, если вы находитесь в терминале. Или, наоборот, если вы хотите изменить параметр из командной строки, попробуйте:

cmake ../Step2 -DUSE_MYMATH=OFF

Теперь пересоберите код следующей командой:

cmake --build .

Затем снова запустите исполняемый файл, чтобы убедиться, что он всё еще работает с параметром USE_MYMATH , установленным на OFF . Какая функция дает лучшие результаты, sqrt или mysqrt ?

Решение

Первый шаг – добавить параметр в файл CMakeLists.txt верхнего уровня. Этот параметр будет отображаться в cmake-gui и ccmake со значением по умолчанию ON , которое может быть изменено пользователем.

TODO 7

option(USE_MYMATH "Use tutorial provided math implementation" ON)

Затем сделайте сборку и компоновку библиотеки MathFunctions условной.

Начните с создания списка необязательных целевых библиотек для нашего проекта с помощью list() . На данный момент это только MathFunctions . Назовем наш список EXTRA_LIBS .

Точно так же нам нужно создать list() для необязательных включений, которые мы назовем EXTRA_INCLUDES . В этом списке мы добавим путь к заголовочному файлу, необходимому для нашей библиотеки.

Затем создайте оператор if() , который проверяет значение USE_MYMATH . Внутри блока if() поместите команду add_subdirectory() из упражнения 1 с дополнительными командами list() .

Когда USE_MYMATH установлена в ON , списки будут сгенерированы и добавлены в наш проект. Когда USE_MYMATH установлена в OFF , списки остаются пустыми. С помощью этой стратегии мы позволяем пользователям переключать USE_MYMATH , чтобы управлять библиотекой, используемой в сборке.

Файл CMakeLists.txt верхнего уровня теперь будет выглядеть следующим образом:

TODO 8

if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) list(APPEND EXTRA_INCLUDES "$/MathFunctions") endif()

Теперь, когда у нас есть эти два списка, нам нужно обновить target_link_libraries() и target_include_directories() . Изменить их достаточно просто.

Для target_link_libraries() мы заменяем записанные имена библиотек на EXTRA_LIBS . Это выглядит следующим образом:

TODO 9

target_link_libraries(Tutorial PUBLIC $)

Затем делаем то же самое с target_include_directories() и EXTRA_INCLUDES .

TODO 10

target_include_directories(Tutorial PUBLIC "$" $ )

Обратите внимание, что это классический подход при работе со многими компонентами. Современный подход мы рассмотрим в шаге 3 данного руководства.

Соответствующие изменения в исходном коде довольно просты. Во-первых, в tutorial.cxx мы включаем заголовок MathFunctions.h , если определена USE_MYMATH .

TODO 11

#ifdef USE_MYMATH # include "MathFunctions.h" #endif

Затем в том же файле мы делаем так, чтобы USE_MYMATH контролировала, какая функция квадратного корня используется:

TODO 12

#ifdef USE_MYMATH const double outputValue = mysqrt(inputValue); #else const double outputValue = sqrt(inputValue); #endif

Поскольку исходный код теперь требует USE_MYMATH , мы можем добавить её в TutorialConfig.h.in с помощью следующей строки:

TODO 13

#cmakedefine USE_MYMATH

С этими изменениями наша библиотека теперь совершенно необязательна для тех, кто ее создает и использует.

Бонусный вопрос

Почему важно сконфигурировать TutorialConfig.h.in после добавления параметра USE_MYMATH ? Что произойдет, если мы перевернем их местами?

Мы конфигурируем его после, потому что TutorialConfig.h.in использует значение USE_MYMATH . Если мы сконфигурируем этот файл перед вызовом option() , мы не будем использовать ожидаемое значение USE_MYMATH .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *