[Ubuntu] simple summary of cmake usage

All contents of this article are from the blog post drawn in summary, thanks [ Love is patient 1989 ] big brother.

Be sure to read the original blog post and then read this one, otherwise it will be messy.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Generally, the composition of a project requires a .h file, a .c file corresponding to the .h, plus a main.c file containing the main function.

If you don't want others to see the specific code inside certain functions, you can just keep the .h files corresponding to these functions, discard the .c files, and use static linking or dynamic linking instead.

cmake can be used to generate Makeile documents corresponding to .h/.c/main.c, and also to generate Makefile documents corresponding to .h/(dynamic/static) links. The key is how to write the CMakeLists.txt file.

The following shows how to write the CMakeLists.txt file in a progressive manner.

1. The simplest usage of CMakeLists.txt

In an empty folder test, create the file testFunc.c to store the function as follows:

#include <stdio.h>
#include "testFunc.h"

void func(int data)
{
	printf("data is %d\n", data);
}

Create the .h file corresponding to testFunc.c as follows:

#ifndef _test_FUNC_H
#define _test_FUNC_H

void func(int data);

#endif

In the test folder, create main.c and edit it as follows:

#include <stdio.h>

int main(void)
{
      func(100);

	return 0;
}

Then, still in the test folder, write CMakeLists.txt as follows:

cmake_minimum_required(VERSION 2.8)

project(demo)

add_executable(main main.c)

Among them, the two statements cmake_minimum and project are mandatory , one specifies the minimum requirements for the cmake version, and the other specifies the name of the project.

add_executable (main main.c) means that the .c file to be used in this project is main.c, and the final executable file generated by this project is named main.

Then execute cmake.. and make in the test folder to generate executable files. 

In this case where all .c and all .h are in the same directory, there is no need to write statements such as include_directories (used to indicate where the .h file is stored) when writing CMakeLists.txt, but all the .c files Just stuff it into add_executable.

(The content of each file will not be clearly written later, it is included in the original blog . This article only writes the MakeLists file)

2. When there are multiple functions, it is convenient to use the aux_source_directiory statement to store all the .c files in a custom variable. as follows:

In the test folder, there are testFunc.c, testFunc.h, testFunc1.c, testFunc1.h, and main.c.

It is still the case that all files belong to the same folder.

For convenience, you can introduce the aux_source_directory statement and write the MakeLists.txt file as follows:

cmake_minimum_required(VERSION 2.8)

project(demo)

aux_source_directory(. SRC_LIST)

add_executable(main ${SRC_LIST})

Here is just to emphasize the role of aux_source_directory, which is to encapsulate all the .c files in a directory into a custom variable.

3. In order to facilitate the search, we put the .c and .h files of different functions in different folders, and the main.c and CMakeLists.txt are placed in the root directory of the project (this article is test), the file The tree is as follows:

Write picture description here

How to write CMakeLists.txt at this time? as follows:

cmake_minimum_required(VERSION 2.8)

project(demo)

include_directories(test_func test_func1)#这条语句的参数是文件夹名称,可以有多个参数,这条语句会自动把每个参数文件夹中包含的.h文件纳入到程序中来

aux_source_directory(test_func SRC_LIST)#这条语句只能有一个文件夹、一个自定义的变量作为参数,不可有多个。这条语句会自动把每个参数文件夹中包含的.c文件纳入到程序中来

aux_source_directory(test_func1 SRC_LIST1)#同上

add_executable(main main.c ${SRC_LIST} ${SRC_LIST1})

The main feature of this example is that the .h file is contained in multiple different paths instead of only one path as before. In this case, use the include_directories function to include all paths that include .h.

In addition, don't be too afraid of the aux_source_directory statement, it is just for the convenience of including all the .c files in the folder into a variable, so as to facilitate the use of add_executable.

Fourth, in order to facilitate the search and use, usually, the root directory of the project (this article is test) contains 4 subdirectories, namely bin, build, include, src, and src stores all the .c files (including main.c). C files of all functions), include stores all .h files, build stores files generated by cmake, and bin stores the final executable files generated.

The file tree structure is as follows:

Write picture description here

In this case, there is a CMakeLists.txt file in test, and a CMakeLists.txt file in src.

The CMakeLists.txt file in test is to show where the source files are, that is, where src is; and the CMakeLists.txt file in src is to show where the files such as .h are.

Among them, the CMakeLists.txt file in test is as follows:

cmake_minimum_required(VERSION 2.8)

project(demo)

add_subdirectory(src)

add_subdirectoroy is to tell the program which folder the source file (ie .c file) is in.

For the CMakeLists.txt in src, note that you don’t need to write cmake_minimum_required and project. The CMakeLists.txt file in src is as follows:

aux_source_directory(. SRC_LIST)

include_directories(../include)

add_executable(main SRC_LIST)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

Comparing the CMakeLists.txt file in the "three" step, it is not difficult to find that the CMakeLists.txt file in this src also contains

(1) Specify the include folder where the .h file is located

(2) Include all .c files into one or some variables

(3)add_executable

Three steps.

But in addition, the statement set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) is added here, which is to specify that the generated executable file is placed in the bin folder.

Finally, go to the build directory and execute cmake.., and then execute make, you can find the generated executable file in the bin.

Five, create static and dynamic libraries

Rebuild the file tree into the following structure:

Write picture description here

There is a CMakeLists.txt file in test, and three folders of build, lib, and lib_testFunc. Among them, the build folder is used to store the files generated by cmake, and the lib is used to store the final static library and dynamic library files. In lib_testFunc Store all the required .c files and .h files.

The content of the CMakeLists.txt file in test is as follows, which is the same as in step "four":

cmake_minimum_required(VERSION 2.8)

project(demo)

add_subdirectory(lib_testFunc)

The content of the CMakeLists.txt file in lib_testFunc is as follows:

aux_source_directory(. SRC_LIST)

add_library(testFunc_shared SHARED ${SRC_LIST})
add_library(testFunc_static STATIC ${SRC_LIST})

set_target_properties(testFunc_shared PROPERTIES OUTPUT_NAME "test_Func")
set_target_properties(testFunc_static PROPERTIES OUTPUT_NAME "test_Func")

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

This file actually contains three parts:

(1) Use the aux_source_directory statement to include all .c files into a custom variable SRC_LIST

(2) Use add_library with SRC_LIST to generate dynamic libraries (shared) and static libraries (static)

     And use set_target_properties to rename the generated library file to "test_Func" (because one is a dynamic library and the other is a static library, the suffixes of the two library files are different, so here you can call them both test_Func, which can still be distinguished)

(3) Use the set statement to specify the folder where the final generated inventory is stored, similar to the previous we used the set statement to specify the folder where the final generated executable file is stored.

Sixth, link main.c with the library file.

Restructure the file tree as follows:

Write picture description here

There is no include folder here, because we put .h in lib_testFunc

The content of the CMakeLists.txt file in the test folder is as follows:

cmake_minimum_required(VERSION 2.8)

project(demo)

add_subdirectory(lib_testFunc)

add_subdirectory(src)

In addition to adding the path where the source file of the function testFunc.c is located, you also need to add the path where the source file of main.c is located, all of which are added with add_subdirectory.

The content of the CMakeLists.txt file in the src folder is as follows:

aux_source_directory(. SRC_LIST)

include_directories(../lib_testFunc)

link_directories(${PROJECT_SOURCE_DIR}/lib)

add_executable(main ${SRC_LIST})

target_link_libraries(main testFunc)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

Attention, for this CMakeLists.txt file in src, what is the difference between when the library file was not used before and when the library file is used now?

After using the library file, we do not need to add the function's .c file, just use include_directories to add the function's .h file; in addition, the new thing is that we need to use link_direcctories to specify the path of the search library, and in the add_executable statement After that, link the executable file name main with the library name testFunc, using the target_link_libraries statement.

Finally, use set to generate executable files.

Guess you like

Origin blog.csdn.net/qq_39642978/article/details/106306131