当前位置:网站首页>Cmake Express

Cmake Express

2022-07-06 16:41:00 Dog egg L

Reprint :

https://blog.csdn.net/whahu1989/article/details/82078563?ops_request_misc=&request_id=&biz_id=102&utm_term=cmake%E4%BD%BF%E7%94%A8&utm_medium=distribute.pc_search_result.none-task-blog-2blogsobaiduweb~default-3-82078563.nonecase&spm=1018.2226.3001.4450

ubuntu install cmake:

apt-get install cmake

A simple example

cmake_minimum_required (VERSION 2.8)

project (demo)

add_executable(main main.c)

The first line means cmake The minimum version requirement for is 2.8, What we have installed is 3.10.2; The second line indicates the information of the project , That is, the name of the project demo; The third line is the key , Represents the final elf The name of the file is main, The source file used is main.c
Switch to... Under the terminal main.c In the directory , Then enter the following command to run cmake .
 Insert picture description here
PS: If you want to regenerate main, Input make clean Can be deleted main This elf file .

Multiple source files in the same directory

Let's move on to a slightly more complex example : There are multiple source files in the same directory .
Add... Under the previous directory 2 File ,testFunc.c and testFunc.h.

cmake_minimum_required (VERSION 2.8)

project (demo)

add_executable(main main.c testFunc.c)

And so on , If there are multiple source files in the same directory , So as long as it's in add_executable Just add all the source files in . But if there are a hundred source files , It's a bit of a pit to do this again , Can't embody cmake The advantages of ,cmake A command is provided to store all source files in a specified directory in a variable , The order is aux_source_directory(dir var).
The first parameter dir Is the specified directory , The second parameter var Is the variable used to store the list of source files .

cmake_minimum_required (VERSION 2.8)

project (demo)

aux_source_directory(. SRC_LIST)

add_executable(main ${
    SRC_LIST})

Use aux_source_directory Save the source files in the current directory in the variable SRC_LIST in , And then in add_executable Call inside SRC_LIST( Pay attention to the writing when calling variables ).
Re execution cmake and make, And run main.

Multiple source files in different directories

Generally speaking , When there are many program files , We will carry out classified management , Put the code in different directories according to the function , This makes it easy to find . So how to write in this case CMakeLists.txt Well ?

cmake_minimum_required (VERSION 2.8)

project (demo)

include_directories (test_func test_func1)

aux_source_directory (test_func SRC_LIST)
aux_source_directory (test_func1 SRC_LIST1)

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

Here comes a new command :include_directories. This command is used to add the search path of multiple specified header files to the project , The paths are separated by spaces .
because main.c in include 了 testFunc.h and testFunc1.h, If you don't have this command to specify the location of the header file , You can't compile . Of course , It can also be in main.c Use in include To specify the path , as follows

#include "test_func/testFunc.h"
#include "test_func1/testFunc1.h"

But this kind of writing is not good-looking .
in addition , We used 2 Time aux_source_directory, Because the source files are distributed in 2 A directory , So add the 2 Time .

Compilation control of dynamic library and static library

Sometimes you just need to compile dynamic and static libraries , Then wait for other programs to use . Let's see how to use in this case cmake.
We will be in build Run in directory cmake, And store the generated library file in lib Under the table of contents .

cmake_minimum_required (VERSION 3.5)

project (demo)

set (SRC_LIST ${
    PROJECT_SOURCE_DIR}/testFunc/testFunc.c)

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

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

set (LIBRARY_OUTPUT_PATH ${
    PROJECT_SOURCE_DIR}/lib)

Here are new commands and predefined variables ,

  • add_library:
    Generate dynamic or static libraries ( The first 1 A parameter specifies the name of the library ; The first 2 Two parameters determine whether it is dynamic or static , If not, the default is static ; The first 3 A parameter specifies the source file of the generated library )

  • set_target_properties: Set the name of the final generated library , There are other functions , Such as setting the version number of the library, etc

  • LIBRARY_OUTPUT_PATH: The default output path of the library file , This is set as... Under the project directory lib Catalog

Okay , Let's get into build Run in directory cmake …, Run after success make

PS: Use... In the front set_target_properties Redefined the output name of the library , If not used set_target_properties It's fine too , So the name of the library is add_library The name defined in , Just continuous 2 Second use add_library An error occurred while specifying the library name ( The first parameter ), This name cannot be the same , and set_target_properties You can set the name to the same , Only the final generated library file has a different suffix ( One is .so, One is .a), This will look better relatively .

Linking Libraries

Now that we have generated the library , Then do the link test . Re create a project directory , Then copy the library generated in the previous section , Then create a new project under the project directory src Contents and bin Catalog , stay src Add a main.c, The overall structure is as follows ,
 Insert picture description here

cmake_minimum_required (VERSION 3.5)

project (demo)


set (EXECUTABLE_OUTPUT_PATH ${
    PROJECT_SOURCE_DIR}/bin)

set (SRC_LIST ${
    PROJECT_SOURCE_DIR}/src/main.c)

# find testFunc.h
include_directories (${
    PROJECT_SOURCE_DIR}/testFunc/inc)

find_library(TESTFUNC_LIB testFunc HINTS ${
    PROJECT_SOURCE_DIR}/testFunc/lib)

add_executable (main ${
    SRC_LIST})

target_link_libraries (main ${
    TESTFUNC_LIB})

It's here 2 A new order ,

  • find_library:
    Find the specified library in the specified directory , And store the absolute path of the library in the variable , The first parameter is the variable name , The second parameter is the library name , The third parameter is HINTS, The first 4 The first parameter is the path , For other usage, please refer to cmake file
  • target_link_libraries: Link the target file to the library file

Use find_library The advantage is to perform cmake … Will find out whether the library exists , In this way, errors can be found in advance , Don't wait for the link .

cd To build Under the table of contents , And then run cmake … && make, Finally, enter bin View under directory , Find out main Generated , Run it ,

ps: stay lib Directory is testFunc Static library and dynamic library ,find_library(TESTFUNC_LIB testFunc ... The default is to find the dynamic library , If you want to directly specify whether to use dynamic library or static library , It can be written. find_library(TESTFUNC_LIB libtestFunc.so ... perhaps find_library(TESTFUNC_LIB libtestFunc.a ...

ps: see elf Which libraries are used by the file , have access to readelf -d ./xx Check it out.

Add compile options

Sometimes you want to add some compilation options when compiling a program , Such as -Wall,-std=c++11 etc. , You can use add_compile_options To operate .

cmake_minimum_required (VERSION 2.8)

project (demo)

set (EXECUTABLE_OUTPUT_PATH ${
    PROJECT_SOURCE_DIR}/bin)

add_compile_options(-std=c++11 -Wall) 

add_executable(main main.cpp)

Add control options

Sometimes you want to compile only the specified source code when compiling code , have access to cmake Of option command , The main situations encountered are divided into 2 Kind of :

  1. It was supposed to generate multiple bin Or library files , Now I just want to generate some of the specified bin Or library files

  2. For the same bin file , Just want to compile some of the code ( Use macros to control )

The first 1 In this case

Suppose our current project will generate 2 individual bin file ,main1 and main2, Now the overall structure is as follows ,
 Insert picture description here

cmake_minimum_required(VERSION 3.5)

project(demo)

option(MYDEBUG "enable debug compilation" OFF)

set (EXECUTABLE_OUTPUT_PATH ${
    PROJECT_SOURCE_DIR}/bin)

add_subdirectory(src)

It's used here option command , The first parameter is this option Name , The second parameter is the string , Used to describe this option What are you doing here , The third is option Value ,ON or OFF, Or not , No writing is the default OFF.

Then write src In the catalog CMakeLists.txt, as follows

cmake_minimum_required (VERSION 3.5)

add_executable(main1 main1.c)

if (MYDEBUG)
    add_executable(main2 main2.c)
else()
    message(STATUS "Currently is not in debug mode")    
endif()

Be careful , It's used here if-else According to option To decide whether to compile main2.c
among main1.c and main2.c Is as follows ,

// main1.c
#include <stdio.h>

int main(void)
{
    
    printf("hello, this main1\n");
    
    return 0;
}

// main2.c
#include <stdio.h>

int main(void)
{
    
    printf("hello, this main2\n");
    
    return 0;
}

then cd To build Enter... In the directory cmake .. && make You can just compile main1, If you want to compile main2, Just put MYDEBUG Set to ON, Input again cmake .. && make recompile .

Every time I want to change MYDEBUG It needs to be modified CMakeLists.txt, A little bit of a problem , You can actually go through cmake Command line to operate , For example, we want to put MYDEBUG Set to OFF, First cd To build Catalog , Then input cmake .. -DMYDEBUG=ON, In this way, you can compile main1 and main2 ( stay bin Under the table of contents )
 Insert picture description here

The first 2 In this case

Suppose we have a main.c, It reads as follows ,

#include <stdio.h>

int main(void)
{
#ifdef WWW1
    printf("hello world1\n");
#endif    

#ifdef WWW2     
    printf("hello world2\n");
#endif

    return 0;
}

You can control the printed information by defining macros , We CMakeLists.txt The contents are as follows ,

cmake_minimum_required(VERSION 3.5)

project(demo)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

option(WWW1 "print one message" OFF)
option(WWW2 "print another message" OFF)

if (WWW1)
    add_definitions(-DWWW1)
endif()

if (WWW2)
    add_definitions(-DWWW2)
endif()

add_executable(main main.c)

Here is the option Keep your name and main.c The macro names in the are consistent , It's more intuitive , You can also choose different names . Through and with add_definitions() With , You can control a single bin A printout of the document .

The overall engineering structure is as follows ,
 Insert picture description here
cd To build Execute under directory cmake .. && make, And then to bin Execute under directory ./main, You can see that the print is empty ,
Then follow the instructions below , Then check the printing effect ,

  • cmake … -DWWW1=ON -DWWW2=OFF && make

  • cmake … -DWWW1=OFF -DWWW2=ON && make

  • cmake … -DWWW1=ON -DWWW2=ON && make

There's a small hole here. You should pay attention to it : Suppose there is 2 individual options It's called A and B, First call cmake Set up A, Next time call cmake To set up B, If the last execution is not deleted cmake Cache file generated when , Well, this time, although it is not set A, Will also default to use A Last time option value .

So if option There are changes , Or delete the last execution cmake Cache file generated when , Or take all of them option Both explicitly specify their values .

原网站

版权声明
本文为[Dog egg L]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060920336056.html