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
91. (Recommended) Acquire source code from mirrors for an officially released version.
10
11   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.
12
13
142. Download the NDK from the SDK Manager in DevEco Studio.
15
16
17## Decompressing the NDK
18
19Place the downloaded NDK in a folder you prefer and decompress it.
20
21Below shows the directory structure after decompression on Windows or Linux.
22
23![en-us_image_0000001726080989](figures/en-us_image_0000001726080989.png)
24
25Below shows the directory structure after decompression on macOS.
26
27![en-us_image_20-24-01-16-14-35](figures/en-us_image_20-24-01-16-14-35.png)
28
29### Configuring the Environment Variable
30Skip this step if the NDK is downloaded from DevEco Studio.
311. Add the CMake tool that comes with the NDK to the environment variables.
32+ Configure the environment variables in Linux.
33
34
35        #Open the .bashrc file.
36        vim ~/.bashrc
37        #Append the custom CMake path to the file.
38        export PATH=~/ohos-sdk/ohos-sdk/linux/native/build-tools/cmake/bin:$PATH
39        #Run the source ~/.bashrc command to make the environment variable take effect.
40        source ~/.bashrc
41
42+ Configure the environment variables in macOS.
43
44  
45        # In the current user directory
46        # Open the .bash_profile file.
47        # If the file does not exist, create one.
48        vim ~/.bash_profile
49        # Append the custom CMake path to the file. Save the file and exit.
50        export PATH=~/Ndk/mac-sdk-full/sdk/packages/ohos-sdk/darwin/native/build-tools/cmake/bin:$PATH
51        # Run the source ~/.bash_profile command to make the environment variable take effect.
52        source ~/.bash_profile
53    
54+ Configure the environment variable in Windows.
55
56  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.)
57  
58  ![en-us_image_20-24-01-16-14-38](figures/en-us_image_20-24-01-16-14-38.png)
59  
60  Verify whether the environment variable is configured successfully.
61
62  Open the CLI and run **F:\windows\native\build-tools\cmake\bin\cmake.exe -version**, replacing the path with the actual CMake path.
63
64  ![en-us_image_20-24-01-16-14-41](figures/en-us_image_20-24-01-16-14-41.png)
65  
66  If the information similar to that shown above is displayed, the environment variable is configured successfully.
67
682. Check the default CMake path.
69   + In Linux or macOS
70      ```
71      #Run the which cmake command.
72      which cmake
73      #The result should be the same as the custom path previously appended to the .bashrc file.
74      ~/ohos-sdk/ohos-sdk/linux/native/build-tools/cmake/bin/cmake
75      ```
76   + In Windows
77     
78     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.
79
80
81## Using the NDK to Compile a Native Program
82
83You 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.
84
85
86### Demo Project
87
88The 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.
89
90**Demo Project Directory**
91
92```
93demo
94  ├── CMakeLists.txt
95  ├── include
96       └── sum.h
97  └── src
98       ├── CMakeLists.txt
99       ├── sum.cpp
100       └── hello.cpp
101```
102
103**CMakeLists.txt in the demo Directory**
104
105```
106# Specify the minimum CMake version.
107CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
108
109# Set the project name, which is HELLO in this example.
110PROJECT(HELLO)
111
112#Add a subdirectory and build the subdirectory.
113ADD_SUBDIRECTORY(src)
114```
115
116**CMakeLists.txt in the src Directory**
117
118```
119SET(LIBHELLO_SRC hello.cpp)
120
121# Set compilation flags.
122SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")   
123 
124# Set the link parameter. The value below is only for exemplary purposes.
125SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--emit-relocs --verbose")    
126
127# Add a libsum dynamic library target. If the compilation is successful, a libsum.so file is generated.
128ADD_LIBRARY(sum SHARED sum.cpp)
129
130# Add the executable target called Hello. If the compilation is successful, a Hello executable is generated.
131ADD_EXECUTABLE(Hello ${LIBHELLO_SRC})
132
133# Specify the path to the include directory of the Hello target.
134TARGET_INCLUDE_DIRECTORIES(Hello PUBLIC ../include)
135
136# Specify the name of the library to be linked to the Hello target.
137TARGET_LINK_LIBRARIES(Hello PUBLIC sum)
138```
139
140**Source Code**
141
142**hello.cpp** source code:
143
144```
145#include <iostream>
146#include "sum.h"
147
148int main(int argc,const char **argv)
149{
150    std::cout<< "hello world!" <<std::endl;
151    int total = sum(1, 100);
152    std::cout<< "Sum 1 + 100=" << total << std::endl;
153    return 0;
154}
155```
156
157**sum.h** source code:
158
159```
160int sum(int a, int b);
161```
162
163**sum.cpp** source code:
164
165```
166#include <iostream>
167    
168int sum(int a, int b)
169{
170    return a + b;
171}
172```
173
174
175### Compiling and Building the Demo Project
176
177#### In Linux or macOS
178In the project directory, create the **build** directory to store the intermediate files generated during CMake building. **NOTE**<br>In the following commands, **ohos-sdk** is the root directory of the downloaded SDK. Replace it with the actual directory.
179
1801. 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.
181
182   ```
183    >mkdir build && cd build
184    >cmake -DOHOS_STL=c++_shared -DOHOS_ARCH=armeabi-v7a -DOHOS_PLATFORM=OHOS -DCMAKE_TOOLCHAIN_FILE={ohos-sdk}/linux/native/build/cmake/ohos.toolchain.cmake ..
185    >cmake --build .
186   ```
187
1882. Use **OHOS_STL=c++_static** to link a static C++ library to build the project.
189
190   ```
191    >mkdir build && cd build
192    >cmake -DOHOS_STL=c++_static -DOHOS_ARCH=armeabi-v7a -DOHOS_PLATFORM=OHOS -DCMAKE_TOOLCHAIN_FILE={ohos-sdk}/linux/native/build/cmake/ohos.toolchain.cmake ..
193    >cmake --build .
194   ```
195
196   In the command, the **OHOS_ARCH** and **OHOS_PLATFORM** variables generate the **--target** options of Clang++.
197   
198   In this example, **--target=arm-linux-ohos** and **--march=armv7a** are generated.
199
200   **CMAKE_TOOLCHAIN_FILE** specifies the toolchain file.
201
202   In this file, **--sysroot={ndk_*sysroot directory*}** is set for Clang++ by default, instructing the compiler to search for the root directory of system header files.
203#### In Windows
204
205Using CMake in Windows, unlike that in Linux, requires you to use the **-G** option to specify the generator.
206
207![en-us_image_20-24-01-16-14-56](figures/en-us_image_20-24-01-16-14-56.png)
208
209In this example, the Ninja generator, which comes with the NDK, is used, as indicated by **-G "Ninja"**.
210
211![en-us_image_20-24-01-16-14-57](figures/en-us_image_20-24-01-16-14-57.png)
212
213Step 1. Create the **build** folder in the project directory and run the following command:
214```
215 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 ..
216```
217Note: If debugging is required, add the **-D CMAKE_BUILD_TYPE=normal** option.
218The CMake path and the ohos.toolchain.cmake path are where the NDK is downloaded.
219The following figure shows the command output.
220
221![en-us_image_20-24-01-16-14-58](figures/en-us_image_20-24-01-16-14-58.png)
222
223The **build.ninja** file generated here is what we need.
224
225Step 2. Use the ninja command to compile and generate the target file. The following figure shows the location of the target file.
226
227![en-us_image_20-24-01-16-14-59](figures/en-us_image_20-24-01-16-14-59.png)
228
229Use **ninja -f build.ninja** or **cmake --build**. The following figure shows the command output.
230
231![en-us_image_20-24-01-16-14-60](figures/en-us_image_20-24-01-16-14-60.png)
232