In this article, you’ll learn how to create a CMake hello world project from scratch using the CMake Tools extension in VS Code.
If you have an existing CMake project that already has a CMakeLists.txt
file in the root directory but no CMake presets, you can skip to Create a CMakePresets.json
file to configure your project with CMake presets.
Otherwise, create a folder for a new project. From the Terminal window, create an empty folder called HelloWorld
, navigate into it, and open VS Code in that folder by entering the following commands:
mkdir helloworld
cd helloworld
code .
The code .
command opens VS Code in the current working folder, which becomes your «workspace».
Create a CMakeLists.txt file
The CMake Tools extension can create the files for a basic CMake project for you.
-
Open the Command Palette (⇧⌘P (Windows, Linux Ctrl+Shift+P)) and run the CMake: Quick Start command:
-
Enter a project name, and select C++ as the project language.
This information will be written to
CMakeLists.txt
and a few initial source files.Note: If you had other source code files in this folder that you wanted to add as targets to the
CmakeLists.txt
, an option to add these would now be given. But for this tutorial, we will stick with just the hello world file. -
Select CTest as an additional option to add support for testing. You can also select CPack for CPack support.
-
Next, select Executable as the project type to create a basic source file (
main.cpp
) that includes a basicmain()
function.Note: If you had wanted to create a basic source and header file, you would have selected Library instead. But for this tutorial, Executable will do. If you are prompted to configure IntelliSense for the folder, select Allow.
This successfully creates the CMakeLists.txt
file, which tells the CMake tools how to build your project.
Create a CMakePresets.json file
Next, continue with the CMake Quick Start to create a CMakePresets.json
file.
-
Select Add a New Preset and Create from Compilers.
The extension automatically scans for kits on your computer and creates a list of compilers found on your system.
-
Select the compiler you want to use.
For example, depending on the compilers you have installed, you might see something like this:
-
Enter a name for this new preset.
The name for the preset will be written to
CMakePresets.json
.
After completing these steps, you should now have a complete hello world CMake project that contains the following files: main.cpp
, CMakeLists.txt
, and CMakePresets.json
.
5/29/2024
Уровень сложностиПростой
Время на прочтение6 мин
Количество просмотров4.2K
Всем привет! На написание данной статьи меня толкнула суровая реальность и лень разбираться с английскими текстами о том, что и куда жмать, дабы собрать адекватный проект на CMake.
Установка CMake тут не рассматривается, вот ссылки:
офф сайт
гайд по установке
Все будет происходить из-под Windows, структурно мало чем будет отличаться от Linux, кроме команд для сборки.
Для начала предлагаю разобраться со структурой проекта в целом:
|Проект №1
|
|CMakeLists.txt #этот лист находится в корне и описывает все группы проектов и папок
|
|--подпроект №1
|----CMakeLists.txt #листы внутри проекта описывают,
|----*.cpp #то как этот проект должен собраться
|----*.h
|
|--подроект №2
|----CMakeLists.txt
|----*.cpp
|----*.h
|
|... (еще кучка проектов)
|
|--include #эта папка содержит те хеддеры библиотек,
|----*.h #которые мы в дальнейшем будем использовать для проектов
|
|--build #как устроена эта папка, может решаться по разному
#хранит скомпилированные фалы (exe lib dll)
#также эта папка хранит кучу сгенерированных файлов CMake
Надеюсь, прочитав данную статью, вы сможете собрать проекты такого формата, но для начала возьмем что-то попроще (старый добрый «Hello World!»).
//hello.cpp
#include <iostream>
int main()
{
std::cout << "Hello world from cmake!"<< std::endl;
return 0;
}
Структура проекта:
|CMakeLists.txt
|
|--hello_world_dir
|----hello.cpp
|
|--build
CMakeLists.txt — это файлы (скрипты) конфигурации проекта, благодаря им мы можем собирать наших проекты. Сейчас мы разберем его простейшую структуру и разберем подходы к сборке проекта.
cmake_minimum_required(VERSION %тут могла быть ваша цифра%) #показывает какой минимальной версией можно собрать проект
project(hello_world) #дает имя проекту
#дает понять что будет собираться исполняеый файл(exe)
#первый аргумент - это название собираемоего проекта, остальные исходные файлы *.h *.cpp
#все аргументы записываются через пробел
add_executable(hello_world hello_world/hello.cpp)
Итак, у нас готов скрипт для сборки нашего первого проекта, рассмотрим же подходы к сборке:
-
собрать все в корневой директории вместе с исходниками {фатальная ошибка};
-
собрать все в отдельно созданной директории для сборки проекта.
Минусы первого подхода достаточно хорошо объясняют, почему так лучше не делать:
-
трудности с сохранением разных сборок проекта
-
захламление корневой директории
Последний шаг: Сборка
Ну а теперь нам нужно залезть в любимый терминал или командную строку. Переходим в корень проекта.
Если просто написать:
cmake
То нам скажут как инициализировать проект или пересобрать его, ну и про --help
упомянут, для получения большей информации
Usage
cmake [options] <path-to-source>
cmake [options] <path-to-existing-build>
cmake [options] -S <path-to-source> -B <path-to-build>
Specify a source directory to (re-)generate a build system for it in the
current working directory. Specify an existing build directory to
re-generate its build system.
Run 'cmake --help' for more information.
Я предлагаю использовать вариант cmake [options] -S <path-to-source> -B <path-to-build
. Ключ -S
устанавливает директорию с исходниками, обязательно содержащую файл CMakeLists.txt
Ключ -B
устанавливает директорию куда будет собираться наш проект. В этой директории будут служебные файлы CMakeCashe
и файлы *.sln для с проектов в VisualStudio, а также директории подпроектов (в Linux данная директория содержит MakeFile)
cmake -S . -B build
Теперь, можно уже и скомпилировать, пишем:
cmake --build <папка содержащая CMakeCache.txt>
В нашем случае данной папкой является build.
cmake --build build
Поздравляю, Вы собрали свой первый проект!
Для такого простого проекта кажется, что все это сплошное нагромождение, поэтому переходим к более сложному проекту.
Проект будет состоять из нашей самописной библиотеки и проекта, который использует эту библиотеку. (весь код будет на github)
Структура проекта:
|
|CMakeLists.txt #основной скрипт сборки, в котором объявляются стандарты языка,
| #места хранения скомпилированных файлов, подключение общих зависимостей
| #подключаются каталоги подпроектов,
|
#подкпроект библиотеки
|--our_lib
|----CMakeLists.txt #скрипт сборки подпроекта
|----*.cpp
|----*.h
|
#подпроект программы использующей библиотеку
|--samples
|----CMakeLists.txt
|----*.cpp
|----*.h
|
#директория с хедарами нашей библиотеки
|--include
|----*.h
|
|--build
Рассмотрим CMakeLists в корне
cmake_minimum_required(VERSION %Ваша цифра%)
set(PROJECT_NAME <имя проекта>)
project(${PROJECT_NAME})
#настраиваем стандарты языка
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#настраиваем места хранения скомпилированных файлов
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE})
#даем названия подпроектам
set(PROG_LIBRARY "${PROJECT_NAME}")
#сораняем путь до директории include нашими хедарами
set(PROG_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/include")
#добавляет путь до нашей директории в область видимости всех проектов
include_directories(${PROG_INCLUDE})
#добавляем директории наших подпроектов в область видимости CMake
add_subdirectory(src)
add_subdirectory(samples)
Команды cmake_minimum_required и project нам уже знакомы. Многочисленная set(<имя>, <значение>)
— создает переменные и объявляет их значения. Благодаря переменным, получается более модифицируемые и универсальные скрипты сборки, также, изменяя значения служебных переменных самого CMake, проект обретает определенные свойства, например: используемый стандарт языка, места хранения скомпилированных файлов и т.д. Перечислять смысл каждой не вижу, так как большинство из них имеют говорящие названия.
${имя_переменной}
— такая конструкция позволяет использовать значение переменных.
include_directories(список путей)
— добавляет директории в область поиска хедеров в проекте.
add_subdirectory(путь до директории)
— добавляет в проект поддиректорию в которой обязательно должен быть файл CMakeLists.txt. В нашем случае это папки с проектом библиотеки и проектом, ее использующим.
Стоит заметить, что все переменные, объявленные в скрипте вызывающем команду, доступны для поддиректорий.
Скрипты сборки в подпроектах нам в целом уже знакомы, для начала рассмотрим библиотечный (/src/CMakeLists.txt).
Пользуясь опытом Hello World, можно написать этот скрипт так:
add_library(${PROG_LIBRARY} STATIC <список всех исходников>)
add_library(<имя> <тип библиотеки> <список исходников>)
— команда аналогичнаяadd_executable
, только для библиотек. (STATIC
— статические библиотеки, SHARED
— динамические).
Да, проект соберется, но постоянно прописывать весь список исходников руками то еще удовольствие, поэтому немного модифицируем скрипт:
set(target ${PROG_LIBRARY})
file(GLOB hdrs "*.h") #команда для работы с файлами
file(GLOB srcs "*.cpp")
add_library(${target} STATIC ${srcs} ${hdrs} )
file()
— команда для работы с файлами, у нее есть множество возможных параметров позволяющих: читать, редактировать, находить,создавать, удалять, загружать … file(GLOB <имя переменной> <регулярное выражение>)
— ищет файлы в текущей директории подходящие регулярному выражению и сохраняет результат в переменную.
Таким образом, скрипт сам ищет исходные файлы (хедеры и cpp) и в add_library
мы просто используем значения сохраненные в переменных.
В Cmake подпроекты называются target (таргетами — целями), поэтому я добавил одноименную переменную для удобства.
Скрипт проекта, использующего библиотеку отличается одной строчкой.
set(target sample)
file(GLOB hdrs "*.h")
file(GLOB srcs "*.cpp")
add_library(${target} STATIC ${srcs} ${hdrs} )
target_link_libraries(${target} ${PROG_LIIBRARY})
target_link_libraries(<имя таргета> <список подключаемых библиотек>)
— подключает библиотеки к выбранному таргету.
Ну и теперь стандартная процедура инициализации и сборки. (не забудьте переместиться в корень или указать правильные пути)
cmake -S . -B build
cmake --build build
Ура, более сложный проект создан и собран!Но, а что если возникли какие-то проблемы во время компиляции отдельного подпроекта(таргета), можно как-то обойтись без сборки всего проекта?
МОЖНО!
cmake --build -t <имя таргета>
Надеюсь, данная статья дала хорошее начало в изучении сборки на CMake.
Как закрепление материала предлагаю подключить вам юнит тесты для нашей самописной библиотеки (гугл тесты). Данную библиотеку можно скомпилировать самому, как отдельную часть проекта, а можно воспользоваться официальным гайдом, чтобы загрузить код непосредственно репозитория (более сложный вариант, дополнительные ссылки будут прикреплены ниже)
helloworld-cmake
This sample is showing you how you can use cmake and CMakeLists.txt file to compile your c++ application.
Environment Setup
Make sure g++ installed. If not go to Build and run your first application with g++ for more help.
Also make sure make command is installed. If not go to Build and run your first application with make for more help.
Run following command to see if cmake is installed:
$ cmake --version
zsh: command not found: cmake
If you face command not found: cmake that means it is not there.
Installing make
- MacOS
- Linux
- Debian/Ubuntu
Building Hello World application
Create a folder called build and then use cmake command to build the application. It uses Makefile compile the sources to object files.
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CC_COMPILER=gcc
-- The C compiler identification is AppleClang 10.0.1.10010046
-- The CXX compiler identification is AppleClang 10.0.1.10010046
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/g++
-- Check for working CXX compiler: /usr/bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
CMake Warning:
Manually-specified variables were not used by the project:
CMAKE_CC_COMPILER
-- Build files have been written to: /Users/nkabiliravi/git/mycpptutorial/helloworld-cmake/build
Now use cmale —build command link the object files into a file called greet:
You can also use make command:
$ make
Scanning dependencies of target greet
[ 33%] Building CXX object CMakeFiles/greet.dir/hello.cpp.o
[ 66%] Building CXX object CMakeFiles/greet.dir/main.cpp.o
[100%] Linking CXX executable greet
[100%] Built target greet
Running the app
Run greet command like this:
$ ./bin/greet
Hello World!
Visit Build and run your first application with cmake to learn more about this sample.
Example
Given a C++ source file main.cpp
defining a main()
function, an accompanying CMakeLists.txt
file (with the following content) will instruct CMake to generate the appropriate build instructions for the current system and default C++ compiler.
main.cpp (C++ Hello World Example)
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.4)
project(hello_world)
add_executable(app main.cpp)
See it live on Coliru
-
cmake_minimum_required(VERSION 2.4)
sets a minimum CMake version required to evaluate the current script. -
project(hello_world)
starts a new CMake project.
This will trigger a lot of internal CMake logic, especially the detection of the default C and C++ compiler. -
With
add_executable(app main.cpp)
a build targetapp
is created, which will invoke the configured compiler with some default flags for the current setting to compile an executableapp
from the given source filemain.cpp
.
Command Line (In-Source-Build, not recommended)
> cmake .
...
> cmake --build .
cmake .
does the compiler detection, evaluates the CMakeLists.txt
in the given .
directory and generates the build environment in the current working directory.
The cmake --build .
command is an abstraction for the necessary build/make call.
Command Line (Out-of-Source, recommended)
To keep your source code clean from any build artifacts you should do «out-of-source» builds.
> mkdir build
> cd build
> cmake ..
> cmake --build .
Or CMake can also abstract your platforms shell’s basic commands from above’s example:
> cmake -E make_directory build
> cmake -E chdir build cmake ..
> cmake --build build
Building is a fairly general term without strict definition; It usually refers to the whole process that outputing the final product (an executable or a library) from source materials. Depending on the requirements, building will involve several of the following: pre-processing, compiling, linking, converting data files, automatically testing, packaging.
Among the tools that defining the building behaviors for Platform Dependent
products whose programming language usually be C
or C++
, CMake is the most popular one as it is open-source and cross-platform. The building process with CMake takes place in two stages:
- Given abstract,
platform and compiler independent
building procedures defined by developers, generating standardMakefile
orProject Files
for IDEs (Visual Studio, Xcode etc.) . - Invoke the desired
native build tool
to undertake the actual building process.
Here we introduce the usage of CMake. The environment of this tutorial is Windows 10
; The output of each command will be different from that running on Linux. For the syntax of CMake Language, you may visit CMake Syntax for details.
Hello World
The following is a good starting point for learning about CMake.
- Create a new folder
test
. - Under the directory, create the source file
main.cpp
.
1
2
3
4
5#include <stdio.h>
int main(){
printf("Hello World from test Main!\n");
return 0;
} - Create the CMake file named exactly
CMakeLists.txt
1
2
3cmake_minimum_required(VERSION 3.10)
project(Main)
add_executable(Main main.cpp) - Run
cmake .
to generate nativeproject files
. UnderWindows
, CMake will generate aVisual Studio
project by default. When finished, lots of contents created in the directory:
1
2
3
4
5
6
7
8
9
10
11
12│ ALL_BUILD.vcxproj
│ ALL_BUILD.vcxproj.filters
│ CMakeCache.txt
│ CMakeLists.txt
│ cmake_install.cmake
│ main.cpp
│ Main.sln
│ Main.vcxproj
│ Main.vcxproj.filters
│ ZERO_CHECK.vcxproj
│ ZERO_CHECK.vcxproj.filters
└─CMakeFiles/ - Run
cmake --build .
to create executable. You could find theMain.exe
in<root-dir>/Debug
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18│ ALL_BUILD.vcxproj
│ ALL_BUILD.vcxproj.filters
│ CMakeCache.txt
│ CMakeLists.txt
│ cmake_install.cmake
│ main.cpp
│ Main.sln
│ Main.vcxproj
│ Main.vcxproj.filters
│ ZERO_CHECK.vcxproj
│ ZERO_CHECK.vcxproj.filters
├─CMakeFiles/
├─Debug/
│ Main.exe
│ Main.ilk
│ Main.pdb
├─Main.dir/
└─x64/ - Run executable via
Debug\Main.exe
1
Hello World from test Main!
Explanation
Generate a Project Buildsystem
To generate a buildsystem
with CMake, the following must be defined:
Source Tree
: The top-level directory containing source files provided by the project. Then the generation will start withCMakeLists.txt
under this directory.Build Tree
: The top-level directory where buildsystem files and output artifacts being placed. CMake will also create aCMakeCache.txt
here to store persistent information.Generator
: The type of buildsystem to generate. If not specified, CMake will choose the proper one automatically. When using one of the Command-Line Build Tool Generators CMake expects that the environment needed by the compiler toolchain is already configured in the shell. When using one of the IDE Build Tool Generators, no particular environment is needed.
You could run CMake with one of the following command signatures to specify them.
cmake [<options>] <path-to-source>
: Then the current directory is the build tree,<path-to-source>
is the source tree. Both absolute an relative path is valid. The source tree must contain aCMakeLists.txt
file and must not contain aCMakeCache.txt
file.cmake [<options>] <path-to-existing-build>
: Then<path-to-existing-build>
is the build tree which must contain aCMakeCache.txt
file because CMake will load the source tree from it.cmake [<options>] -S <path-to-source> -B <path-to-build>
. Specify both<path-to-build>
and<path-to-source>
. The source tree must contain aCMakeLists.txt
file; The build tree will be created automatically if it does not already exist.
Options
For the full list of options please visit https://cmake.org/cmake/help/latest/manual/cmake.1.html#options or cmake --help
-C <initial-cache>
: Pre-load a script that contains a list ofset()
commands to initialize the cache values. The loaded entries take priority over the project’s default values.-D <var>:<type>=<value>
or-D <var>=<value>
: Create or update a CMake CACHE entry.-G <generator-name>
Specify a build system generator. Runcmake --help
to get the name of supported generators--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>
: Set the log level. Themessage()
command will only output messages of the specified log level or higher. The default log level isSTATUS
.
Build a Project
Use cmake --build <dir> [<options>] [-- <build-tool-options>]
to build an already-generated project binary tree.
--build <dir>
The binary directory when building.--parallel [<jobs>], -j [<jobs>]
: Specify the maximum number of concurrent processes. If<jobs>
is omitted, use the default number.--target <tgt>..., -t <tgt>...
: Build specific<tgt>
s .--config <cfg>
: For multi-configuration tools, choose specific<cfg>
.--clean-first
: Clean existing built target and re-build it.-target clean
: Clean existing built target only.
Output message
message([SEND_ERROR|STATUS|FATAL_ERROR|DEBUG|TRACE] "message text" ...)
CMake displays STATUS
to TRACE
messages on stdout with prefix --
; All other message types are sent to stderr. FATAL_ERROR
will terminate the process immediately whereas CMake Error
stops generation only but continues processing.
Set Project Name
project(<PROJECT-NAME> [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]])
This command will set the name of the project and store it in PROJECT_NAME
. When called from the top-level CMakeLists.txt
, it will also store the project name in CMAKE_PROJECT_NAME
. Simultaneously, the variables PROJECT_SOURCE_DIR
, <PROJECT-NAME>_SOURCE_DIR
, PROJECT_BINARY_DIR
, <PROJECT-NAME>_BINARY_DIR
will be defined according to the absolute path of the corresponding directory.
Add Executable
add_executable(<name> [source1] [source2 ...])
This command will add an executable target called <name>
to be built from the source files listed in the command invocation; The source files can also be added later using target_sources()
. The <name>
must be globally unique within a project. By default the executable will be created in the build tree directory with the name <name>
or <name>.exe
depending on the native platform.
In-Source and Out-of-Source Build
Some build trees created with GNU autotools have a make distclean
command that removes Makefiles and others belonging to the generated build system. However, CMake has no way to track exactly which files are generated by itself. Therefore, it’s recommended to adopt the out-of-source
build —- placing the build tree separately from the source tree. Then one can clean the build by clear or delete the build tree without affect the original source files.
A Better Hello World
Reorganize the Project Directory
- Create
src/
to place source files - Create
CMakeLists.txt
undersrc/
- Create
build/
to place buildsystem
After that, the structure of our project will be
1 |
| CMakeLists.txt |
Config Source and Binary Directory
1 |
add_subdirectory(source_dir [binary_dir]) |
This command will add source_dir
run its CMakeLists.txt
; A relative path will be evaluated with respect to the current directory. The binary_dir
specifies the directory in which to place the output files. Both relative path and absolute path are valid; A relative path it will be evaluated with respect to the current output directory. If binary_dir
is not specified, the value of source_dir
before expanding will be used.
In top-level CMakeLists.txt
become:
1 |
cmake_minimum_required(VERSION 3.10) |
Config Source Directory
It’s tedious to list all source files manually, regardless of using
1 |
add_executable(project source1.c source2.c) |
or
1 |
set(DIR source1.c source2.c) |
aux_source_directory(<dir> <variable>)
will collects the names of all the source files in <dir>
and stores the list in the <variable>
. Note that there is no way for the build system that knows when a new source file has been added; When a new source is just added to the directory, one would have to manually rerun CMake to generate a build system incorporating the new file.
In CMakeLists.txt
of src/
, add
1 |
aux_source_directory(. SRC_DIR) |
Config Binary Directory
In CMakeLists.txt
of src/
, add
1 |
aux_source_directory(. SRC_DIR) |
Specify the C++ Standard
In top-level CMakeLists.txt
, add
1 |
set(CMAKE_CXX_STANDARD 11) |
Add a Version Number
Add the version number in project
.
1 |
project(Main VERSION 1.0) |
Then the variables PROJECT_VERSION
, <PROJECT-NAME>_VERSION
, PROJECT_VERSION_MAJOR
, <PROJECT-NAME>_VERSION_MAJOR
, PROJECT_VERSION_MINOR
, <PROJECT-NAME>_VERSION_MINOR
, PROJECT_VERSION_PATCH
, <PROJECT-NAME>_VERSION_PATCH
, PROJECT_VERSION_TWEAK
, <PROJECT-NAME>_VERSION_TWEAK
will be defined accordingly.
It’s also valid to specify the version number directly in the source code,; Using CMakeLists.txt
provides more flexibility. Under src/
, create a new file config.h.in
with the following content:
1 |
|
configure_file(<input> <output>)
will copy the <input>
to an <output>
file with the evaulated values referenced as @VAR@
or ${VAR}
. Each variable reference will be replaced with the current value of the variable, or the empty string if the variable is not defined.
The configured file will be written into the ${CMAKE_CURRENT_BINARY_DIR}
; We must add that directory to the list of paths to search for include files. In src/CMakeLists.txt
, add
1 |
configure_file(config.h.in config.h) |
target_include_directories(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...]) [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
specifies include directories to when compiling a given target. The named <target>
must have been defined by such as add_executable()
or add_library()
.
Finally, in main.cpp
, let’s include the header file and print the version number.
1 |
#include <stdio.h> |
A Complex Hello World
Add Math Library
Create math/
under src/
, add CMakeLists.txt
, MathFunctions.cpp
with MathFunctions.h
MathFunctions.h
1 |
extern double power(double base, int exponent); |
MathFunctions.cpp
1 |
#include "MathFunctions.h" |
src/math/CMakeLists.txt
1 |
aux_source_directory(. DIR_LIB_SRCS) |
After that, the structure will be
1 |
| CMakeLists.txt |
Build and Use Static Library
In src/math/CMakeLists.txt
, add
1 |
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) |
add_library(<name> [STATIC | SHARED] [source1] [source2 ...])
will add a library target called <name>
.
The top-level CMakeLists.txt
become:
1 |
cmake_minimum_required(VERSION 3.10) |
The src/CMakeLists.txt
become:
1 |
aux_source_directory(. SRC_DIR) |
The structure become
1 |
| CMakeLists.txt |
Build and use Dynamic Library
src/math/CMakeLists.txt
become
1 |
aux_source_directory(. DIR_LIB_SRCS) |
MathFunctions.h
become
1 |
extern __declspec( dllexport ) double power(double base, int exponent); |
src/CMakeLists.txt
become:
1 |
aux_source_directory(. SRC_DIR) |
Then the structrue become
1 |
| CMakeLists.txt |
When running with dynamic-linked library, you should put the .dll
s under the same folder of .exe
.
https://cmake.org/cmake/help/latest/guide/tutorial/ https://cliutils.gitlab.io/modern-cmake/