Как установить cmake на windows
Знакомство с CMake. Часть 1. Установка, CMakeLists.txt, сборка.
Введение.
Многие, кто начинал создавать собственные программы, пользовался какой-либо системой сборки. В общем, система сборки – это набор инструментов, облегчающий работу с компилятором. Это включает в себя компиляцию, линковку, установку, а также сбор исходных файлов для передачи их компилятору и слежение за зависимостями. Также современные системы сборки облегчают работу с библиотеками, позволяют создавать переносимые проекты и выполняют ещё массу других вкусностей. Эта статья посвящена популярной системе сборки CMake и расскажет, как правильно её установить и настроить, а также будет рассмотрен простой пример её использования. Она рассчитана на тех, что хоть немного знаком с понятиями make, Makefile, компиляция, линковка.
Установка в Linux.
Для популярных дистрибутивов Linux типа Debian, Gentoo, Fedora и т.д. CMake давно лежит в официальных репозиториях. Нам нужно всего лишь установить пакет cmake с помощью менеджера пакетов. Как правило, он устанавливается в системные директории, и необходимости править переменные окружения нету. Можете проверить её работоспособность, выполнив
Если же в репозитории нет такого пакета, то можно его собрать вручную. Скачиваем Unix/Linux Source, например, cmake-3.5.0-rc3.tar.gz, распаковываем и собираем:
Установка в Windows.
Для Windows на сайте CMake лежит установочный файл msi. Рекомендую при установке отметить галочку добавления пути в переменные окружения PATH для всех пользователей. Тогда, после перелогинивания, CMake будет доступен из любого места. Проверить можно, открыв cmd и выполнив тот же
Русские Блоги
Учебник по установке и использованию VSCode CMake
обзор
При использовании cmake для компиляции программ на C / C ++ в Windows вам сначала понадобится CMake, установите среду компиляции gcc / g ++, затем используйте VSCode и настройте CMakelist.txt.
Что такое CMake
Возможно, вы слышали о нескольких инструментах Make, таких как GNU Make, Qmake QT, MS nmake от Microsoft, BSD Make (pmake), Makepp и так далее. Эти инструменты Make следуют различным спецификациям и стандартам, и формат исполняемого ими файла Makefile сильно различается. Это создает серьезную проблему: если программное обеспечение хочет кросс-платформенное, оно должно гарантировать, что оно может быть скомпилировано на разных платформах. Если вы используете вышеупомянутый инструмент Make, вы должны написать Makefile для каждого стандарта, что будет сумасшедшей работой.
Обычно процесс генерации и компиляции Makefile с использованием CMake выглядит следующим образом:
готов
1. VSCode (следующие плагины должны быть установлены)
C/C++
C++ Intellisense
CMake
CMake tools
CMake Tools Helper
2. MinGW, руководство по установке [Портал】
3.CMake
Установить CMake
Настройте CMake в VSCode
Как правило, после того, как вы просто установите плагин CMake, вам будет автоматически предложено выбрать цепочку инструментов компиляции. Если подсказки нет или вы хотите заменить другие цепочки инструментов компиляции, вы можете использовать ctrl + shiftl + p, ввести следующие инструкции, а затем выбрать собственную установленную компиляцию во всплывающем окне. Цепочка для инструментов.
CMake:Select a Kit
Использование CMake
Теперь мы создаем каталог со следующей структурой:
Код main.c выглядит следующим образом:
Чтобы скомпилировать этот файл, мы редактируем файл CMakeLists.txt следующим образом:
Затем войдите в каталог Build и выполните cmake
Вывод выглядит следующим образом, и в папке Build создается много файлов, включая файл Makefile.
Файлы, содержащиеся в папке Build
На данный момент мы используем make Команда, вы можете скомпилировать нашу программу.
Наконец, попробуйте, результат нормальный.
Русские Блоги
Использование CMAKE и его внедрение
О CMake
Возможно, вы слышали о нескольких инструментах Make, таких как GNU Make, qmake QT, MS nmake от Microsoft, Make BSD (pmake), Makepp и так далее. Эти инструменты Make следуют различным спецификациям и стандартам, и формат исполняемого ими файла Makefile сильно различается. Это создает серьезную проблему: если программное обеспечение хочет кросс-платформенное, оно должно гарантировать, что оно может быть скомпилировано на разных платформах. Если вы используете вышеупомянутый инструмент Make, вы должны написать Makefile для каждого стандарта, что будет сумасшедшей работой.
Используйте CMake на Windows
Также очень удобно использовать CMake в Windows.В дополнение к традиционному методу командной строки использования CMake, существует также простая программа с графическим интерфейсом cmake-gui.exe для использования CMake.
Установить CMake
Установить CMake на Windows легко, идиhttps://cmake.org/ Загрузите последний установочный пакет CMake выше. Во время установки вы также можете выбрать, добавлять ли CMake в PATH системы, как показано на следующем рисунке:
Для удобства CMake можно добавить в системный PATH.
Использование CMake GUI
Окно редактирования сборки двоичных файлов представляет собой каталог промежуточных файлов и конечных двоичных файлов, которые компилируются и выводятся.
Поскольку в конечном итоге CMake генерирует соответствующий файл проекта VS в Windows через файл CMakeLists.txt, различные версии VS также влияют на окончательный файл проекта VS, поэтому в диалоговом окне настройки необходимо выбрать инструмент компиляции кода, как показано на рисунке:
Ниже в качестве примера используется код тестового проекта Google для использования CMake-gui, введите путь, соответствующий тесту Google, и нажмите кнопку «Создать», чтобы создать компиляцию в каталоге E: / googletest / googletest / build. Файлы проекта:
Откройте файл gtest.sln с помощью vs, и вы можете скомпилировать тестовый код Google.
Использование командной строки CMake
Использование командной строки в CMake более сложное, чем в GUI, но оно более мощное и заслуживает изучения. Ниже приведен метод вызова командной строки CMake:
Генерация скомпилированных файлов проекта
Таким образом, мы передали новое значение EXECUTABLE_OUTPUT_PATH в сценарий компиляции CMakeLists.txt.
Скомпилируйте проект
В дополнение к генерации файлов проекта компиляции, CMake может также вызвать проект системы компиляции для компиляции проекта, например:
Режим командной строки
Написать CMakeLists.txt
Создать исполняемую программу
Сначала начните с создания простейшей исполняемой программы. Содержимое CMakeLists.txt выглядит следующим образом:
4 указывают, что мы создали проект с именем LearnCMake, соответствующий LearnCMake.sln. Функция проекта означает создание проекта. В то же время были сгенерированы 4 переменные:
По умолчанию создается консольный проект, плюс WIN32 указывает, что проект win32 создан следующим образом:
Позади кода проекта, вы можете добавить несколько файлов кода, разделенных пробелами.
Создать проект библиотеки
Создание проекта библиотеки аналогично созданию проекта исполняемой программы. Создание проекта библиотеки использует функцию add_library. Следующий пример:
Использование add_library выглядит следующим образом:
По умолчанию используется статическая библиотека, и вы также можете явно указать, является ли библиотека статической библиотекой, динамической библиотекой или модулем. Кроме того, BUILD_SHARED_LIBS также может контролировать, в какую библиотеку компилируется.
target_link_libraries используется для связывания библиотек, используется следующим образом:
установить установить переменную
Add_library и add_executable могут добавлять несколько исходных файлов следующим образом:
Мы можем заменить app_util.h app_util.cpp, определив переменную AppUtilSrc следующим образом:
Эффект эквивалентен вышеуказанному. Вы также можете накапливать значения:
Итак, AppUtilSrcs представляет 3 файла.
Установить режим компиляции
Установите режим компиляции mt:
Установите режим компиляции md:
По умолчанию используется многобайтовый режим, установленный в режим Unicode:
Кроме того, add_definitions может также установить другие параметры.
Добавить другие CMakeLists.txt
Если цель в CMakeLists.txt должна быть связана с целями в другом CMakeLists.txt, вы можете использовать add_subdirectory. Давайте возьмем библиотеку googletest в качестве примера:
Контроль кода
Добавьте заголовочный файл, включающий каталог:
Но файлы в include_directories не будут отражены в первом проекте Visual Studio, а aux_source_directory будет только добавлять исходные файлы и игнорировать файлы заголовков. Если проект Visual Studio, который вы хотите сохранить, также содержит файлы заголовков, вы можете сделать это:
Если вы хотите пережить фильтр в visual studio, вы можете использовать source_group:
Стандартный шаблон для добавления файла заголовка в проект:
installВ¶
Specify rules to run at install time.
SynopsisВ¶
IntroductionВ¶
This command generates installation rules for a project. Install rules specified by calls to the install() command within a source directory are executed in order during installation.
Changed in version 3.14: Install rules in subdirectories added by calls to the add_subdirectory() command are interleaved with those in the parent directory to run in the order declared (see policy CMP0082 ).
There are multiple signatures for this command. Some of them define installation options for files and targets. Options common to multiple signatures are covered here but they are valid only for signatures that specify them. The common options are:
Specify the directory on disk to which a file will be installed. Arguments can be relative or absolute paths.
If a relative path is given it is interpreted relative to the value of the CMAKE_INSTALL_PREFIX variable. The prefix can be relocated at install time using the DESTDIR mechanism explained in the CMAKE_INSTALL_PREFIX variable documentation.
If an absolute path (with a leading slash or drive letter) is given it is used verbatim.
As absolute paths are not supported by cpack installer generators, it is preferable to use relative paths throughout. In particular, there is no need to make paths absolute by prepending CMAKE_INSTALL_PREFIX ; this prefix is used by default if the DESTINATION is a relative path.
Specify a list of build configurations for which the install rule applies (Debug, Release, etc.). Note that the values specified for this option only apply to options listed AFTER the CONFIGURATIONS option. For example, to set separate install paths for the Debug and Release configurations, do the following:
Specify that the file is excluded from a full installation and only installed as part of a component-specific installation
Specify a name for an installed file that may be different from the original file. Renaming is allowed only when a single file is installed by the command.
Specify that it is not an error if the file to be installed does not exist.
New in version 3.1: Command signatures that install files may print messages during installation. Use the CMAKE_INSTALL_MESSAGE variable to control which messages are printed.
New in version 3.11: Many of the install() variants implicitly create the directories containing the installed files. If CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS is set, these directories will be created with the permissions specified. Otherwise, they will be created according to the uname rules on Unix-like platforms. Windows platforms are unaffected.
Installing TargetsВ¶
The TARGETS form specifies rules for installing targets from a project. There are several kinds of target Output Artifacts that may be installed:
Target artifacts of this kind include:
On AIX, the linker import file created for executables with ENABLE_EXPORTS enabled.
Target artifacts of this kind include:
Shared libraries, except
on macOS when marked as FRAMEWORK (see below).
Target artifacts of this kind include:
DLLs (on all Windows-based systems including Cygwin; note that the accompanying import libraries are of kind ARCHIVE ).
Object files associated with object libraries.
Both static and shared libraries marked with the FRAMEWORK property are treated as FRAMEWORK targets on macOS.
Executables marked with the MACOSX_BUNDLE property are treated as BUNDLE targets on macOS.
Any PUBLIC_HEADER files associated with a library are installed in the destination specified by the PUBLIC_HEADER argument on non-Apple platforms. Rules defined by this argument are ignored for FRAMEWORK libraries on Apple platforms because the associated files are installed into the appropriate locations inside the framework folder. See PUBLIC_HEADER for details.
For each of these arguments given, the arguments following them only apply to the target or file type specified in the argument. If none is given, the installation properties apply to all target types. If only one is given then only targets of that type will be installed (which can be used to install just a DLL or just an import library.)
The following table shows the target types with their associated variables and built-in defaults that apply when no destination is given:
Projects wishing to follow the common practice of installing headers into a project-specific subdirectory will need to provide a destination rather than rely on the above.
In addition to the common options listed above, each target can accept the following additional arguments:
New in version 3.12.
On some platforms a versioned shared library has a symbolic link such as:
Consider the following example:
In this scenario, if you choose to install only the Development component, both the headers and namelink will be installed without the library. (If you don’t also install the Libraries component, the namelink will be a dangling symlink, and projects that link to the library will have build errors.) If you install only the Libraries component, only the library will be installed, without the headers and namelink.
This option is typically used for package managers that have separate runtime and development packages. For example, on Debian systems, the library is expected to be in the runtime package, and the headers and namelink are expected to be in the development package.
See the VERSION and SOVERSION target properties for details on creating versioned shared libraries.
This option causes the installation of only the namelink when a library target is installed. On platforms where versioned shared libraries do not have namelinks or when a library is not versioned, the NAMELINK_ONLY option installs nothing. It is an error to use this parameter outside of a LIBRARY block.
When NAMELINK_ONLY is given, either NAMELINK_COMPONENT or COMPONENT may be used to specify the installation component of the namelink, but COMPONENT should generally be preferred.
The install(TARGETS) command can also accept the following options at the top level:
New in version 3.21.
This option causes all runtime dependencies of installed executable, shared library, and module targets to be added to the specified runtime dependency set. This set can then be installed with an install(RUNTIME_DEPENDENCY_SET) command.
This keyword and the RUNTIME_DEPENDENCIES keyword are mutually exclusive.
New in version 3.21.
RUNTIME_DEPENDENCIES is semantically equivalent to the following pair of calls:
where will be a randomly generated set name. The args. may include any of the following keywords supported by the install(RUNTIME_DEPENDENCY_SET) command:
The RUNTIME_DEPENDENCIES and RUNTIME_DEPENDENCY_SET keywords are mutually exclusive.
will install myExe to
The RUNTIME_DEPENDENCY_SET option causes the runtime artifacts of the imported executable, shared library, and module library targets to be added to the runtime dependency set. This set can then be installed with an install(RUNTIME_DEPENDENCY_SET) command.
Installing FilesВ¶
Projects wishing to follow the common practice of installing headers into a project-specific subdirectory will need to provide a destination rather than rely on the above.
Note that some of the types’ built-in defaults use the DATAROOT directory as a prefix. The DATAROOT prefix is calculated similarly to the types, with CMAKE_INSTALL_DATAROOTDIR as the variable and share as the built-in default. You cannot use DATAROOT as a TYPE parameter; please use DATA instead.
Installing DirectoriesВ¶
The DIRECTORY form installs contents of one or more directories to a given destination. The directory structure is copied verbatim to the destination. The last component of each directory name is appended to the destination directory but a trailing slash may be used to avoid this because it leaves the last component empty. Directory names given as relative paths are interpreted with respect to the current source directory. If no input directory names are given the destination directory will be created but nothing will be installed into it. The FILE_PERMISSIONS and DIRECTORY_PERMISSIONS options specify permissions given to files and directories in the destination. If USE_SOURCE_PERMISSIONS is specified and FILE_PERMISSIONS is not, file permissions will be copied from the source directory structure. If no permissions are specified files will be given the default permissions specified in the FILES form of the command, and the directories will be given the default permissions specified in the PROGRAMS form of the command.
New in version 3.1: The MESSAGE_NEVER option disables file installation status output.
will extract and install header files from a source tree.
Some options may follow a PATTERN or REGEX expression as described under string(REGEX) and are applied only to files or directories matching them. The EXCLUDE option will skip the matched file or directory. The PERMISSIONS option overrides the permissions setting for the matched file or directory. For example the code
Note that some of the types’ built-in defaults use the DATAROOT directory as a prefix. The DATAROOT prefix is calculated similarly to the types, with CMAKE_INSTALL_DATAROOTDIR as the variable and share as the built-in default. You cannot use DATAROOT as a TYPE parameter; please use DATA instead.
New in version 3.5: The list of dirs. given to DIRECTORY may use «generator expressions» too.
Custom Installation LogicВ¶
The SCRIPT form will invoke the given CMake script files during installation. If the script file name is a relative path it will be interpreted with respect to the current source directory. The CODE form will invoke the given CMake code during installation. Code is specified as a single argument inside a double-quoted string. For example, the code
will print a message during installation.
New in version 3.21: When the ALL_COMPONENTS option is given, the custom installation script code will be executed for every component of a component-specific installation. This option is mutually exclusive with the COMPONENT option.
Installing ExportsВ¶
-config.cmake file or the latter may be incorrectly matched by the glob and loaded.
New in version 3.7: In addition to cmake language files, the EXPORT_ANDROID_MK mode maybe used to specify an export to the android ndk build system. This mode accepts the same options as the normal export mode. The Android NDK supports the use of prebuilt libraries, both static and shared. This allows cmake to build the libraries of a project and make them available to an ndk build system complete with transitive dependencies, include flags and defines required to use the libraries.
The EXPORT form is useful to help outside projects use targets built and installed by the current project. For example, the code
will install the executable myexe to
Installs a runtime dependency set previously created by one or more install(TARGETS) or install(IMPORTED_RUNTIME_ARTIFACTS) commands. The dependencies of targets belonging to a runtime dependency set are installed in the RUNTIME destination and component on DLL platforms, and in the LIBRARY destination and component on non-DLL platforms. macOS frameworks are installed in the FRAMEWORK destination and component. Targets built within the build tree will never be installed as runtime dependencies, nor will their own dependencies, unless the targets themselves are installed with install(TARGETS).
CMake TutorialВ¶
IntroductionВ¶
The CMake tutorial provides a step-by-step guide that covers common build system issues that CMake helps address. Seeing how various topics all work together in an example project can be very helpful. The tutorial documentation and source code for examples can be found in the Help/guide/tutorial directory of the CMake source code tree. Each step has its own subdirectory containing code that may be used as a starting point. The tutorial examples are progressive so that each step provides the complete solution for the previous step.
A Basic Starting Point (Step 1)В¶
The most basic project is an executable built from source code files. For simple projects, a three line CMakeLists.txt file is all that is required. This will be the starting point for our tutorial. Create a CMakeLists.txt file in the Step1 directory that looks like:
Note that this example uses lower case commands in the CMakeLists.txt file. Upper, lower, and mixed case commands are supported by CMake. The source code for tutorial.cxx is provided in the Step1 directory and can be used to compute the square root of a number.
Adding a Version Number and Configured Header FileВ¶
The first feature we will add is to provide our executable and project with a version number. While we could do this exclusively in the source code, using CMakeLists.txt provides more flexibility.
First, modify the CMakeLists.txt file to use the project() command to set the project name and version number.
Then, configure a header file to pass the version number to the source code:
Since the configured file will be written into the binary tree, we must add that directory to the list of paths to search for include files. Add the following lines to the end of the CMakeLists.txt file:
Using your favorite editor, create TutorialConfig.h.in in the source directory with the following contents:
When CMake configures this header file the values for @Tutorial_VERSION_MAJOR@ and @Tutorial_VERSION_MINOR@ will be replaced.
Finally, let’s print out the executable name and version number by updating tutorial.cxx as follows:
Specify the C++ StandardВ¶
Build and TestВ¶
Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool.
For example, from the command line we could navigate to the Help/guide/tutorial directory of the CMake source code tree and create a build directory:
Next, navigate to the build directory and run CMake to configure the project and generate a native build system:
Then call that build system to actually compile/link the project:
Finally, try to use the newly built Tutorial with these commands:
Adding a Library (Step 2)В¶
Now we will add a library to our project. This library will contain our own implementation for computing the square root of a number. The executable can then use this library instead of the standard square root function provided by the compiler.
Add the following one line CMakeLists.txt file to the MathFunctions directory:
To make use of the new library we will add an add_subdirectory() call in the top-level CMakeLists.txt file so that the library will get built. We add the new library to the executable, and add MathFunctions as an include directory so that the mysqrt.h header file can be found. The last few lines of the top-level CMakeLists.txt file should now look like:
Now let us make the MathFunctions library optional. While for the tutorial there really isn’t any need to do so, for larger projects this is a common occurrence. The first step is to add an option to the top-level CMakeLists.txt file.
This option will be displayed in the cmake-gui and ccmake with a default value of ON that can be changed by the user. This setting will be stored in the cache so that the user does not need to set the value each time they run CMake on a build directory.
The next change is to make building and linking the MathFunctions library conditional. To do this we change the end of the top-level CMakeLists.txt file to look like the following:
Note the use of the variable EXTRA_LIBS to collect up any optional libraries to later be linked into the executable. The variable EXTRA_INCLUDES is used similarly for optional header files. This is a classic approach when dealing with many optional components, we will cover the modern approach in the next step.
Then, in the same file, make USE_MYMATH control which square root function is used:
Since the source code now requires USE_MYMATH we can add it to TutorialConfig.h.in with the following line:
Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool. Then run the built Tutorial executable.
Rebuild and run the tutorial again.
Which function gives better results, sqrt or mysqrt?
Adding Usage Requirements for Library (Step 3)В¶
Usage requirements allow for far better control over a library or executable’s link and include line while also giving more control over the transitive property of targets inside CMake. The primary commands that leverage usage requirements are:
Let’s refactor our code from Adding a Library (Step 2) to use the modern CMake approach of usage requirements. We first state that anybody linking to MathFunctions needs to include the current source directory, while MathFunctions itself doesn’t. So this can become an INTERFACE usage requirement.
Remember INTERFACE means things that consumers require but the producer doesn’t. Add the following lines to the end of MathFunctions/CMakeLists.txt :
Installing and Testing (Step 4)В¶
Now we can start adding install rules and testing support to our project.
Install RulesВ¶
The install rules are fairly simple: for MathFunctions we want to install the library and header file and for the application we want to install the executable and configured header.
So to the end of MathFunctions/CMakeLists.txt we add:
And to the end of the top-level CMakeLists.txt we add:
That is all that is needed to create a basic local install of the tutorial.
Now run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool.
Navigate to the install directory and verify that the installed Tutorial runs.
Testing SupportВ¶
Next let’s test our application. At the end of the top-level CMakeLists.txt file we can enable testing and then add a number of basic tests to verify that the application is working correctly.
The first test simply verifies that the application runs, does not segfault or otherwise crash, and has a zero return value. This is the basic form of a CTest test.
The next test makes use of the PASS_REGULAR_EXPRESSION test property to verify that the output of the test contains certain strings. In this case, verifying that the usage message is printed when an incorrect number of arguments are provided.
Adding System Introspection (Step 5)В¶
Let us consider adding some code to our project that depends on features the target platform may not have. For this example, we will add some code that depends on whether or not the target platform has the log and exp functions. Of course almost every platform has these functions but for this tutorial assume that they are not common.
If available, use target_compile_definitions() to specify HAVE_LOG and HAVE_EXP as PRIVATE compile definitions.
If log and exp are available on the system, then we will use them to compute the square root in the mysqrt function. Add the following code to the mysqrt function in MathFunctions/mysqrt.cxx (don’t forget the #endif before returning the result!):
Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool and run the Tutorial executable.
Which function gives better results now, sqrt or mysqrt?
Adding a Custom Command and Generated File (Step 6)В¶
Suppose, for the purpose of this tutorial, we decide that we never want to use the platform log and exp functions and instead would like to generate a table of precomputed values to use in the mysqrt function. In this section, we will create the table as part of the build process, and then compile that table into our application.
In the MathFunctions subdirectory, a new source file named MakeTable.cxx has been provided to generate the table.
After reviewing the file, we can see that the table is produced as valid C++ code and that the output filename is passed in as an argument.
The next step is to add the appropriate commands to the MathFunctions/CMakeLists.txt file to build the MakeTable executable and then run it as part of the build process. A few commands are needed to accomplish this.
Then we add a custom command that specifies how to produce Table.h by running MakeTable.
Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool.
Run the Tutorial executable and verify that it is using the table.
Building an Installer (Step 7)В¶
Finally we include the CPack module which will use these variables and some other properties of the current system to setup an installer.
The next step is to build the project in the usual manner and then run the cpack executable. To build a binary distribution, from the binary directory run:
To create a source distribution you would type:
Alternatively, run make package or right click the Package target and Build Project from an IDE.
Run the installer found in the binary directory. Then run the installed executable and verify that it works.
Adding Support for a Dashboard (Step 8)В¶
We will also need to create a CTestConfig.cmake file in the top-level directory where we can specify the name of the project and where to submit the dashboard.
The ctest executable will read in this file when it runs. To create a simple dashboard you can run the cmake executable or the cmake-gui to configure the project, but do not build it yet. Instead, change directory to the binary tree, and then run:
Remember, for multi-config generators (e.g. Visual Studio), the configuration type must be specified:
Or, from an IDE, build the Experimental target.
The ctest executable will build and test the project and submit the results to Kitware’s public dashboard: https://my.cdash.org/index.php?project=CMakeTutorial.
Mixing Static and Shared (Step 9)В¶
The first step is to update the starting section of the top-level CMakeLists.txt to look like:
Now that we have made MathFunctions always be used, we will need to update the logic of that library. So, in MathFunctions/CMakeLists.txt we need to create a SqrtLibrary that will conditionally be built and installed when USE_MYMATH is enabled. Now, since this is a tutorial, we are going to explicitly require that SqrtLibrary is built statically.
The end result is that MathFunctions/CMakeLists.txt should look like:
Next, update MathFunctions/mysqrt.cxx to use the mathfunctions and detail namespaces:
Always include MathFunctions.h
Always use mathfunctions::sqrt
Don’t include cmath
Finally, update MathFunctions/MathFunctions.h to use dll export defines:
At this point, if you build everything, you may notice that linking fails as we are combining a static library without position independent code with a library that has position independent code. The solution to this is to explicitly set the POSITION_INDEPENDENT_CODE target property of SqrtLibrary to be True no matter the build type.
Exercise: We modified MathFunctions.h to use dll export defines. Using CMake documentation can you find a helper module to simplify this?
Adding Generator Expressions (Step 10)В¶
Generator expressions are evaluated during build system generation to produce information specific to each build configuration.
Generator expressions may be used to enable conditional linking, conditional definitions used when compiling, conditional include directories and more. The conditions may be based on the build configuration, target properties, platform information or any other queryable information.
There are different types of generator expressions including Logical, Informational, and Output expressions.
So the following code:
Would be replaced with:
Next we add the desired compiler warning flags that we want for our project. As warning flags vary based on the compiler we use the COMPILE_LANG_AND_ID generator expression to control which flags to apply given a language and a set of compiler ids as seen below:
Looking at this we see that the warning flags are encapsulated inside a BUILD_INTERFACE condition. This is done so that consumers of our installed project will not inherit our warning flags.
Adding Export Configuration (Step 11)В¶
During Installing and Testing (Step 4) of the tutorial we added the ability for CMake to install the library and headers of the project. During Building an Installer (Step 7) we added the ability to package up this information so it could be distributed to other people.
The next step is to add the necessary information so that other CMake projects can use our project, be it from a build directory, a local install or when packaged.
Now that we have MathFunctions being exported, we also need to explicitly install the generated MathFunctionsTargets.cmake file. This is done by adding the following to the bottom of the top-level CMakeLists.txt :
At this point you should try and run CMake. If everything is setup properly you will see that CMake will generate an error that looks like:
What CMake is trying to say is that during generating the export information it will export a path that is intrinsically tied to the current machine and will not be valid on other machines. The solution to this is to update the MathFunctions target_include_directories() to understand that it needs different INTERFACE locations when being used from within the build directory and from an install / package. This means converting the target_include_directories() call for MathFunctions to look like:
Once this has been updated, we can re-run CMake and verify that it doesn’t warn anymore.
At this point, we have CMake properly packaging the target information that is required but we will still need to generate a MathFunctionsConfig.cmake so that the CMake find_package() command can find our project. So let’s go ahead and add a new file to the top-level of the project called Config.cmake.in with the following contents:
Then, to properly configure and install that file, add the following to the bottom of the top-level CMakeLists.txt :
At this point, we have generated a relocatable CMake Configuration for our project that can be used after the project has been installed or packaged. If we want our project to also be used from a build directory we only have to add the following to the bottom of the top level CMakeLists.txt :
Packaging Debug and Release (Step 12)В¶
Note: This example is valid for single-configuration generators and will not work for multi-configuration generators (e.g. Visual Studio).
By default, CMake’s model is that a build directory only contains a single configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is possible, however, to setup CPack to bundle multiple build directories and construct a package that contains multiple configurations of the same project.
First, we want to ensure that the debug and release builds use different names for the executables and libraries that will be installed. Let’s use d as the postfix for the debug executable and libraries.
Set CMAKE_DEBUG_POSTFIX near the beginning of the top-level CMakeLists.txt file:
And the DEBUG_POSTFIX property on the tutorial executable:
From the Step12 directory, create debug and release subbdirectories. The layout will look like:
Now we need to setup debug and release builds. We can use CMAKE_BUILD_TYPE to set the configuration type:
Next, use the CPACK_INSTALL_CMAKE_PROJECTS variable to specify which projects to install. In this case, we want to install both debug and release.
From the Step12 directory, run cpack specifying our custom configuration file with the config option: