Hello everyone, in the last article I shared the first part of the cmake article: CMake Learning Summary (Part 1). Today, I will continue to share more about cmake. Without further ado, let’s get started.
1. Make Good Use of CMake, Be Happy All Day (Even…):
1. For multiple source files, use the command aux_source_directory(dir var):
At the end of the last article, there was a question about what to do when you have multiple source files in the same directory. You can’t manually add all the source files to the third command below, as that would be very inefficient:
cmake_minimum_required(VERSION 2.8)
project(main)
add_executable(main main.c test1.c)
To solve this inefficiency, there is a command in cmake that can completely solve this problem. However, to illustrate the issue, I added two more files: test2.c and test2.h:
root@txp-virtual-machine:/home/txp/test# ls
1 cmake_install.cmake main.c test1.h touch1.c
CMakeCache.txt CMakeLists.txt Makefile test2.c touch1.h
CMakeFiles main test1.c test2.h
The content of test2.c is as follows:
#include <stdio.h>
#include "test2.h"
void func1()
{
printf("i like the cmake\n");
}
The content of test2.h is as follows:
#ifndef _TEST2_H_
#define _TEST2_H_
void func1();
#endif
Finally, the main.c calls the func1 function:
#include <stdio.h>
#include "test1.h"
#include "test2.h"
int main(void)
{
func1();
func(8);
printf("TXP Embedded\n");
return 0;
}
Now, the focus is on how to use aux_source_directory(dir var) in cmake to solve the above inefficiency problem. Next, we will operate in CMakeLists.txt like this:
cmake_minimum_required(VERSION 2.8)
project(main)
aux_source_directory(. SRC_LIST)
add_executable(main ${SRC_LIST})
Then compile:
root@txp-virtual-machine:/home/txp/test# cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/txp/test
root@txp-virtual-machine:/home/txp/test# make
Scanning dependencies of target main
[ 25%] Building C object CMakeFiles/main.dir/main.c.o
[ 50%] Linking C executable main
root@txp-virtual-machine:/home/txp/test# ./main
i like the cmake
the b is 8
TXP Embedded
Explanation:
aux_source_directory(. SRC_LIST) means to add all source files in the current directory to the source list variable. Finally, use add_executable(main ${SRC_LIST}) to process all useful source files into the target file main. However, this method has its drawbacks, as it adds all source files in the current directory to the variable SRC_LIST. If we do not need some unused files (only the required source files are needed), we can operate like this:
cmake_minimum_required(VERSION 2.8)
project(main)
set(SRC_LIST
./main.c
./test1.c
./test2.c
)
add_executable(main ${SRC_LIST})
This can also be compiled:
root@txp-virtual-machine:/home/txp/test# cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/txp/test
root@txp-virtual-machine:/home/txp/test# make
[100%] Built target main
2. In the above example, we find that the source files in the same directory are quite messy. Therefore, in cmake, there is a rule that allows us to put related source files of the same type in the same directory. For example, I now create two directories test1 and test2 under the test directory, and place test1.c, test1.h, test2.c, and test2.h in these two directories respectively:
root@txp-virtual-machine:/home/txp/test# mkdir -p test1 test2
root@txp-virtual-machine:/home/txp/test# ls
@ CMakeFiles main test1 test2
1 cmake_install.cmake main.c test1.c test2.c
CMakeCache.txt CMakeLists.txt Makefile test1.h test2.h
Then move the related files into these two directories:
root@txp-virtual-machine:/home/txp/test# mv test1.c test1.h test1
root@txp-virtual-machine:/home/txp/test# mv test2.c test2.h test2
root@txp-virtual-machine:/home/txp/test# ls
@ CMakeCache.txt cmake_install.cmake main Makefile test2
1 CMakeFiles CMakeLists.txt main.c test1
root@txp-virtual-machine:/home/txp/test# tree
├── cmake_install.cmake
├── CMakeLists.txt
├── main
├── main.c
├── Makefile
├── test1
│ ├── test1.c
│ └── test1.h
└── test2
├── test2.c
└── test2.h
Then at this point, we need to modify the rules in CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(main)
include_directories(test1 test2)
aux_source_directory(test1 SRC_LIST)
aux_source_directory(test2 SRC_LIST1)
add_executable(main main.c ${SRC_LIST} ${SRC_LIST1})
Then the compilation output can also pass:
root@txp-virtual-machine:/home/txp/test# cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/txp/test
root@txp-virtual-machine:/home/txp/test# make
Scanning dependencies of target main
[ 25%] Building C object CMakeFiles/main.dir/main.c.o
[ 50%] Building C object CMakeFiles/main.dir/test1/test1.c.o
[ 75%] Building C object CMakeFiles/main.dir/test2/test2.c.o
[100%] Linking C executable main
[100%] Built target main
root@txp-virtual-machine:/home/txp/test# ls
@ CMakeCache.txt cmake_install.cmake main Makefile test2
1 CMakeFiles CMakeLists.txt main.c test1
root@txp-virtual-machine:/home/txp/test# ./main
i like the cmake
the b is 8
TXP Embedded
Explanation:
Here, a new command appears: include_directories. This command is used to add multiple specified header file search paths to the project, separated by spaces.
In actual development projects, source files are generally placed in the src directory, header files in the include directory, generated object files in the build directory, and the final output elf files in the bin directory. This way, it looks clear at a glance. Haha, more details can be found in the next issue breakdown. That’s all for today’s learning summary. Hope it’s useful to you.
