1# Building an NDK Project with CMake
2
3
4In many complex application projects, C++ projects are compiled and built in command line mode through build systems such as CMake. The following describes how to switch an existing CMake project to the OpenHarmony toolchain so that CMake can be used to build the project.
5
6
7## Downloading the NDK
8<!--RP1-->
91. (Recommended) Acquire source code from mirrors for an officially released version. Specifically, access the release notes of the target version, locate the **Acquiring Source Code from Mirror** section, and download the source code based on your system type.
10
11
122. Download the NDK from the SDK Manager in DevEco Studio.
13<!--RP1End-->
14
15## Decompressing the NDK
16
17Place the downloaded NDK in a folder you prefer and decompress it.
18
19Below shows the directory structure after decompression on Windows or Linux.
20
21![en-us_image_0000001726080989](figures/en-us_image_0000001726080989.png)
22
23Below shows the directory structure after decompression on macOS.
24
25![en-us_image_20-24-01-16-14-35](figures/en-us_image_20-24-01-16-14-35.png)
26
27### Configuring the Environment Variable
28Skip this step if the NDK is downloaded from DevEco Studio.
291. Add the CMake tool that comes with the NDK to the environment variables.
30+ Configure the environment variables in Linux.
31
32  ```
33  # Open the .bashrc file.
34  vim ~/.bashrc
35  # Append the custom CMake path to the file. Save the file and exit.
36  export PATH=${sdk_path}/native/build-tools/cmake/bin:$PATH
37  # Run the source ~/.bashrc command to make the environment variable take effect.
38  source ~/.bashrc
39  ```
40
41+ Configure the environment variables in macOS.
42
43  ```
44  #In the current user directory, open the .bash_profile file. If the file does not exist, create one.
45  vim ~/.bash_profile
46  #Append the custom CMake path to the file. Save the file and exit.
47  export PATH=${sdk_path}/native/build-tools/cmake/bin:$PATH
48  #Run the source ~/.bash_profile command to make the environment variable take effect.
49  source ~/.bash_profile
50  ```
51
52+ Configure the environment variable in Windows.
53
54  Right-click **This PC** and choose **Properties** from the shortcut menu. In the displayed dialog box, click the **Advanced System Settings** tab and then click **Environment Variables**. Under **System Variables** dialog box, select the **Path** environment variable and click **Edit**. Add the paths, save the settings, and exit. (If the next step cannot be performed, restart the computer.)
55
56  ![en-us_image_20-24-01-16-14-38](figures/en-us_image_20-24-01-16-14-38.png)
57
58  Open the CLI and run **{*cmake_installation_path*}\cmake.exe -version** command. If the CMake version number is displayed correctly, the environment variable configuration is complete.
59
60  ![en-us_image_20-24-01-16-14-41](figures/en-us_image_20-24-01-16-14-41.png)
61
62
632. Check the default CMake path.
64   + In Linux or macOS
65      ```
66      #Run the which cmake command.
67      which cmake
68      #The result should be the same as the custom path previously appended to the .bashrc file.
69      ~/ohos-sdk/ohos-sdk/linux/native/build-tools/cmake/bin/cmake
70      ```
71   + In Windows
72
73     Right-click **This PC** and choose **Properties** from the shortcut menu. In the displayed dialog box, click the **Advanced System Settings** tab and then click **Environment Variables**. Under **System Variables** dialog box, check the **Path** value. The displayed CMake path should be the one you have added.
74
75
76## Using the NDK to Compile a Native Program
77
78You can use the NDK to quickly develop a native program, including native dynamic libraries, static libraries, and executable files. The following exemplifies how to use the NDK to compile an executable program and a dynamic library in a C/C++ demo project.
79
80
81### Demo Project
82
83The following is a CMake demo project. This project contains two directories. The **include** directory contains the header files of the library, and the **src** directory contains all source code. Specifically, the **src** directory contains two files: **sum.cpp** (algorithm file) and **main.cpp** (main entry file for invoking algorithms). The two files are compiled into an executable program and an algorithm dynamic library.
84
85**Demo Project Directory**
86
87```
88demo
89  ├── CMakeLists.txt
90  ├── include
91       └── sum.h
92  └── src
93       ├── CMakeLists.txt
94       ├── sum.cpp
95       └── hello.cpp
96```
97
98**CMakeLists.txt in the demo Directory**
99
100```
101# Specify the minimum CMake version.
102CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
103
104# Set the project name, which is HELLO in this example.
105PROJECT(HELLO)
106
107#Add a subdirectory and build the subdirectory.
108ADD_SUBDIRECTORY(src)
109```
110
111**CMakeLists.txt in the src Directory**
112
113```
114SET(LIBHELLO_SRC hello.cpp)
115
116# Set compilation flags.
117SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
118
119# Set the link parameter. The value below is only for exemplary purposes.
120SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--emit-relocs --verbose")
121
122# Add a libsum dynamic library target. If the compilation is successful, a libsum.so file is generated.
123ADD_LIBRARY(sum SHARED sum.cpp)
124
125# Add the executable target called Hello. If the compilation is successful, a Hello executable is generated.
126ADD_EXECUTABLE(Hello ${LIBHELLO_SRC})
127
128# Specify the path to the include directory of the Hello target.
129TARGET_INCLUDE_DIRECTORIES(Hello PUBLIC ../include)
130
131# Specify the name of the library to be linked to the Hello target.
132TARGET_LINK_LIBRARIES(Hello PUBLIC sum)
133```
134
135**Source Code**
136
137**hello.cpp** source code:
138
139```
140#include <iostream>
141#include "sum.h"
142
143int main(int argc,const char **argv)
144{
145    std::cout<< "hello world!" <<std::endl;
146    int total = sum(1, 100);
147    std::cout<< "Sum 1 + 100=" << total << std::endl;
148    return 0;
149}
150```
151
152**sum.h** source code:
153
154```
155int sum(int a, int b);
156```
157
158**sum.cpp** source code:
159
160```
161#include <iostream>
162
163int sum(int a, int b)
164{
165    return a + b;
166}
167```
168
169
170### Compiling and Building the Demo Project
171
172#### In Linux or macOS
173In the project directory, create the **build** directory to store the intermediate files generated during CMake building.
174
175> **NOTE**
176>
177> In the following commands, **ohos-sdk** is the root directory of the downloaded SDK. Replace it with the actual directory.
178
1791. Use **OHOS_STL=c++_shared** to dynamically link the C++ library to build a project. If **OHOS_STL** is not specified, **c++_shared** is used by default. Set **DOHOS_ARCH** based on the system architecture.
180
181   ```
182    >mkdir build && cd build
183    >cmake -DOHOS_STL=c++_shared -DOHOS_ARCH=armeabi-v7a -DOHOS_PLATFORM=OHOS -DCMAKE_TOOLCHAIN_FILE={ohos-sdk}/linux/native/build/cmake/ohos.toolchain.cmake ..
184    >cmake --build .
185   ```
186
1872. Use **OHOS_STL=c++_static** to link a static C++ library to build the project.
188
189   ```
190    >mkdir build && cd build
191    >cmake -DOHOS_STL=c++_static -DOHOS_ARCH=armeabi-v7a -DOHOS_PLATFORM=OHOS -DCMAKE_TOOLCHAIN_FILE={ohos-sdk}/linux/native/build/cmake/ohos.toolchain.cmake ..
192    >cmake --build .
193   ```
194
195   In the command, the **OHOS_ARCH** and **OHOS_PLATFORM** variables ultimately generate the **--target** command argument for Clang++. In this example, they correspond to the **--target=arm-linux-ohos** and **--march=armv7a** arguments.
196
197   In the **CMAKE_TOOLCHAIN_FILE** file, **--sysroot={ndk_*sysroot_directory*}** is set for Clang++ by default, instructing the compiler to search for the root directory of system header files.
198
199#### In Windows
200
201Using CMake in Windows, unlike that in Linux, requires you to use the **-G** option to specify the generator.
202
203![en-us_image_20-24-01-16-14-56](figures/en-us_image_20-24-01-16-14-56.png)
204
205In this example, the Ninja generator, which comes with the NDK, is used, as indicated by **-G "Ninja"**.
206
207![en-us_image_20-24-01-16-14-57](figures/en-us_image_20-24-01-16-14-57.png)
208
209Step 1. Create the **build** folder in the project directory and run the following command:
210```
211 F:\windows\native\build-tools\cmake\bin\cmake.exe -G "Ninja" -D OHOS_STL=c++_shared -D OHOS_ARCH=armeabi-v7a -D OHOS_PLATFORM=OHOS -D CMAKE_TOOLCHAIN_FILE=F:\windows\native\build\cmake\ohos.toolchain.cmake ..
212```
213Note: If debugging is required, add the **-D CMAKE_BUILD_TYPE=normal** option. The CMake path and the ohos.toolchain.cmake path are where the NDK is downloaded.
214The following figure shows the command output.
215
216![en-us_image_20-24-01-16-14-58](figures/en-us_image_20-24-01-16-14-58.png)
217
218The **build.ninja** file generated is what we need.
219
220Step 2. Use the ninja command to compile and generate the target file. The following figure shows the location of the target file.
221
222![en-us_image_20-24-01-16-14-59](figures/en-us_image_20-24-01-16-14-59.png)
223
224Use **ninja -f build.ninja** or **cmake --build**. The following figure shows the command output.
225
226![en-us_image_20-24-01-16-14-60](figures/en-us_image_20-24-01-16-14-60.png)
227