|
大家晚上好,在这里祝大家端午安康。今天给大家分享的是工程管理工具cmake,没有先介绍makefile工程管理工具(坦白来说,这两者都差不多,cmake最终还是会生成Makefile的,只是说cmake语法稍微比较简单一些,没有Makefile那么复杂!)。就自己个人经历,现在一般公司去写Makefile和cmake的比较少(当然去招聘网站上,有的时候还是可以看到有这个技能要求会写的,所以说能够自己写出来是最为完美的!),一般都是直接使用厂家的Makefile或者Cmake;但作为学习,还是要认真学习里面的原理,比如出现了错误,你要能够定位到错误并把它解决掉,因为可能错误就出现在配置好的Makefile或者Cmake里面,所以你要看的懂里面代码的意思(也就是说,你知道这个工具是这样用,但是也要明白它的原理机制,做到之知其然,知其所以个然来!),这样才能把问题解决掉。 而且就个人见解,在传统的linux工程管理用Makefile的比较多(Uboot里面也是大量使用Makefile来进行管理工程);在新型领域,比如物联网开发(特别是一些开源项目等),用Cmake的比较多(当然也有可能是例外哈!);好了,废话就不多说了,开始来学习了: 一、Cmake学习使用: 1、安装Cmake管理工具: 一般实际嵌入式linux开发,几乎都是用Ubuntu来开发的,因为那啥,安装啥应用程序的非常方便,只需一个命令“apt install + 应用程序名称” 大部分都直接搞定,不用再去配置(特殊的,就例外,还要一些其他相关配置!),安装Cmake就是一条命令直接搞定: root@txp-virtual-machine:/home/txp# apt install cmakeReading package lists... Done, H# ^4 V9 V7 I) g! w/ a @ Building dependency tree & [1 D; I6 \% _( R; H0 S 2、先从一个简单示例,来得出一般书写步骤规律: 这里先写一个简单的代码工程main.c,然后再使用我们的cmake来管理代码工程: #include <stdio.h>2 d( N0 }$ d* s) Z2 ~3 Xint main(void) { printf("TXP嵌入式\n"); return 0;4 s# P2 {) ~; a6 c2 e 2 Q- t) Q& X0 g } 然后开始写cmake工程管理文件,我在当前目录建立一个CMakeLists.txt文件,然后再往里面开始工程管理代码 root@txp-virtual-machine:/home/txp/test# pwd/home/txp/test root@txp-virtual-machine:/home/txp/test# touch CMakeLists.txt5 b0 x' u" s. G- v root@txp-virtual-machine:/home/txp/test# ls& m2 Z- E8 A0 n" g6 B3 \ CMakeLists.txt main.c& u9 j) o) @# V `' S4 ^5 `) ~ ) R8 m6 P3 _1 z- C9 W% I+ ?5 j; U CMakeLists.txt文件里面的内容如下: cmake_minimum_required (VERSION 2.8)project (main)# A% k# o, o% v' ^3 {' I! f add_executable(main main.c) * F# b3 ?! u. Y& O. m 解释一下这三条语句分别代表什么意思: 1、表示cmake最低执行版本是2.8才有效来管理我们的工程项目。 2、表示整个工程名为main 3、表示最终要生成的elf文件的名字叫main,使用的源文件是main.c 现在我们来实现cmake的功能,在当前目录下,使用命令"cmake ."(.表示当前目录,而..表示上一级目录),生成makefile等相关文件;然后再执行一下make命令进行编译工程,就能生成可执行文件main了,同时也会生成makefile文件,最后就可以执行可执行main文件,就能得到我们所要的结果: root@txp-virtual-machine:/home/txp/test# cmake .-- The C compiler identification is GNU 4.8.4& o' w. {* b1 k+ n: V -- The CXX compiler identification is GNU 4.8.4 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works( R! [- r$ O `! H/ H -- Detecting C compiler ABI info7 y! i9 u& ~5 C# _' | -- Detecting C compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works( U. \5 u% [: r% q+ O4 n3 L, m -- Detecting CXX compiler ABI info# p8 r+ [+ K2 R6 V. ? -- Detecting CXX compiler ABI info - done -- Configuring done -- Generating done, y0 s& Z4 @ u6 a+ N -- Build files have been written to: /home/txp/test/ y# s. d. V! v1 E / z' j$ W6 P4 { z9 n% f 7 u- i& L+ {( C/ n root@txp-virtual-machine:/home/txp/test# ls' a, g+ [! Z% Q CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt main main.c Makefile4 q! q1 I2 a6 A" l root@txp-virtual-machine:/home/txp/test# make! K9 S d; A, i# S1 e! K5 r Scanning dependencies of target main [100%] Building C object CMakeFiles/main.dir/main.c.o9 e0 f& ?3 u* o* S: \ Linking C executable main9 B8 g3 l6 v0 L% q- c6 b6 N [100%] Built target main ! i& M( x' L% N8 e% l+ N 6 t2 D% [$ Z3 T+ M, m- j root@txp-virtual-machine:/home/txp/test# ./main: N& N. f% k4 N6 `: r }. x8 U TXP嵌入式 $ j" N* Z: y8 P! Z8 P 如果你再好奇一下的话,可以打开看看Makefile里面的内容是啥,很容易想到是用makefile的方式来实现对工程main的管理,这里我就不画蛇添足把源代码贴出来了。cmake_install.cmake 是一些相关配置选项: # Install script for directory: /home/txp/test- @( v8 w- M5 X3 D" W2 e8 Y$ b8 j5 C/ ^5 x # Set the install prefix9 V+ ]) s w% A" Z( J IF(NOT DEFINED CMAKE_INSTALL_PREFIX)" N8 g, G5 j" ?- m' K SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)! P/ l4 @* y- T: b, i' e& _* v0 `' N STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name.. ^- A& |2 n% |; G- Z IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE)4 n/ [- y# D* A- }( a' \ STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE)) _- N: f3 A9 L" T( y) ? SET(CMAKE_INSTALL_CONFIG_NAME "")* h( a% i5 P8 n: }1 T) {% d, w. | ENDIF(BUILD_TYPE)5 f- s) f4 x# j' l MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)0 h: X+ }. W! i: V8 ]) Q3 a( e # Set the component getting installed.' v5 ~: |. S9 |0 l4 n2 N$ I IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT)0 q7 {: ^; u1 k C3 x% W MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")7 S+ ?- i) w( S: Q# j' ^ ELSE(COMPONENT)2 Q% H+ s5 Y% L6 o SET(CMAKE_INSTALL_COMPONENT)$ Q% S9 h: l5 W" W& ~( v" O ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) ' u) O Y) G2 ` # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)% D j4 e# D1 c SET(CMAKE_INSTALL_SO_NO_EXE "1")" B: r9 M7 c, i. F ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)" [4 \7 o8 |8 r9 A5 _* T* R/ z; O 8 W' _; z: F8 \ IF(CMAKE_INSTALL_COMPONENT)1 u0 a7 S2 \3 @# z2 q6 t! w, { SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")3 i9 H2 F% B$ Y' \ T& F6 F ELSE(CMAKE_INSTALL_COMPONENT)* }6 `4 U8 B7 m0 b F4 F/ X SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt")% I1 \2 C9 S% P$ t, P/ T ENDIF(CMAKE_INSTALL_COMPONENT)8 D8 Y/ a- k8 h) y" h- q( C! V; u! ^ FILE(WRITE "/home/txp/test/${CMAKE_INSTALL_MANIFEST}" "")0 Z F" P$ \' K+ @/ ~2 X0 | FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES}) FILE(APPEND "/home/txp/test/${CMAKE_INSTALL_MANIFEST}" "${file}\n")- d# C5 K9 l& E2 k2 E ENDFOREACH(file) ~ 8 b6 O# [2 L* s3 t; W9 Y- K 而CMakeFiles是一个文件夹,里面文件内容如下: root@txp-virtual-machine:/home/txp/test/CMakeFiles# ls2.8.12.2 cmake.check_cache CMakeDirectoryInformation.cmake ; ]: P4 [* n7 u+ I8 H. H CMakeOutput.log CMakeTmp main.dir Makefile2 + n* s; k5 B7 A- z Makefile.cmake progress.marks TargetDirectories.txt. M0 m( M* m% f/ @ + Z8 O% g. h! v 小结: 从上面简单的示例我们可以看出,Cmake所有的语句都是写在一个名为"CMakeLists.txt"的文本文件里面,所以完成一个工程用cmake管理的完整步骤如下: 1、先建立CMakeLists.txt(这跟我们用makefile来管理工程一样,都有一个特殊的文件来专门书写工程管理代码的,cmake也不例外,使用CMakeLists.txt文本文件来专门书写代码管理工程项目)。 2、然后进行往CMakeLists.txt写配置,具体简单配置参考上面的形式写,复杂的配置,我们会在下面进行演示讲解的。 3、接着使用命令"cmake .",这里必须是CMakeLists.txt同级目录下执行这个命令哈,生成makefile等文件 4、最后使用make命令进行工程编译,进而生成可执行文件。 3、同一个目录有多个源文件: 这里我们在当前目录再添加两个文件:test1.c和test1.h。test1.c文件内容如下: #include <stdio.h>#include "test1.h" void func(int a) {0 u" ?* ? t( M- { printf("a=%d\n",a);* \' w, [( |; {: z& h6 z } test1.h里面的内容如下: #ifndef _TEST1_H; U# \0 a8 K) G" y" Y: x#define _TEST1_H( M! t" S( b, b' M0 h. k% X; m void func(int a); #endif /* _TEST1_H */ 然后在main。c里面进行调用func()这个函数: #include <stdio.h>% Y H8 O# ^/ U; Y#include "test1.h" int main(void) {$ d4 U. b2 L# D; c8 S {4 d" R. t! C i( A func(6);/ s- k9 o- W. Q printf("TXP嵌入式\n");" I# @6 G8 x4 G; E' K s return 0; 4 v- D0 p1 w( V( O } 0 c# i# o" n4 P; [ 然后这个时候我们的CMakeLists.txt里面书写形式肯定要改了: cmake_minimum_required (VERSION 2.8)8 j- {1 z! F1 z2 k+ Y# e project (main)* Y0 Q! p; V+ E3 l: v- n' `; }: a+ s7 C add_executable(main main.c test1.c) 最终结果如下: 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 [ 50%] Building C object CMakeFiles/main.dir/main.c.o- A6 K! G. H! E! D0 |: H* ` [100%] Building C object CMakeFiles/main.dir/test1.c.o" }4 g7 K G# m5 G Linking C executable main [100%] Built target main" o8 Y" O' s' J! j a% G; f root@txp-virtual-machine:/home/txp/test# ls 1 CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt main main.c Makefile test1.c test1.h root@txp-virtual-machine:/home/txp/test# ./main a=6 TXP嵌入式 小结: 上面的CMakeLists.txt的写法,你会注意到add_executable(main main.c test1.c)多了一个源文件(你可以把源码看作成加工的原材料,在makefile里面也是这样来理解目标文件的生成!),所以如果你还要往当前目录下添加源文件的话,在书写CMakeLists.txt文本文件时,直接在第三个语句里面添加源文件;不过这种方式有缺陷,比如说,如果当前文件下有几百个源文件,这个时候你不可能一个个去手写敲吧,不然这样就又回到了原始社会,就不能体现cmake的优越性出来了!更多用法,且听下回细解! |
微信公众号
手机版
希望楼主多多分享,赠人玫瑰,手有余香,念念不忘,必有回响;