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