Introduction

This article provides a straightforward set of “Hello World!” introductions to using CMake for building C++ projects. All steps are performed using Linux on the BeagleBone platform, but the instructions are relevant to most Linux platforms.

The make utility and Makefiles provide a build system that can be used to manage the compilation and re-compilation of programs that are written in any programming language. I use Makefiles quite often in my projects to automate the build process; however, there are times when Makefiles become overly complex for the task — particularly when building projects that have multiple sub directories, or projects that are to be deployed to multiple platforms.

Building complex projects is where CMake really shines — CMake is a cross-platform Makefile generator! Simply put, CMake automatically generates the Makefiles for your project. It can do much more than that too (e.g., build MS Visual Studio solutions), but in this discussion I focus on the auto-generation of Makefiles for C/C++ projects.

GET SOURCE CODE

Source Code for this Discussion

All of the code for this discussion is available in the GitHub repository for the book Exploring BeagleBone. The code can be viewed publicly at: the ExploringBB GitHub CMake Example Projects directory, and/or you can clone the repository on your BeagleBone (or other Linux device) by typing:

1

2

molloyd@beaglebone:~$ sudo apt-get install git

molloyd@beaglebone:~$ git clone https://github.com/derekmolloy/exploringBB.git

Example 1: The Hello World Example

The first project is contained in the extras/cmake/helloworld directory of the GitHub repository. In this example a simple “Hello World” C++ program is built (HelloWorld.cpp), which has the source code provided in Listing 1.

Listing 1: The Hello World C++ Example

1

2

3

4

5

6

#include<iostream>

int main(int argc, char *argv[]){

std::cout << "Hello World!" << std::endl;

return 0;

}

There is only one other file required in the same directory, CMakeLists.txt, which contains the contents of Listing 2.

Listing 2: The Simple Project CMakeLists.txt file

1

2

3

cmake_minimum_required(VERSION 2.8.9)

project (hello)

add_executable(hello helloworld.cpp)

The CMakeLists.txt file in Listing 2 consists of only three lines:

  • The first line sets the minimum version of CMake for this project, which is major version 2, minor version 8, and patch version 9 in this example. This version is somewhat arbitrary in this example, but providing a version number allows for future support for your build environment. Therefore, you should use the current version of CMake on your system, which for this example is determined just below.
  • The second line is the project() command that sets the project name.
  • The third line is the add_executable() command, which requests that an executable is to be built using the helloworld.cpp source file. The first argument to the add_executable() function is the name of the executable to be built, and the second argument is the source file from which to build the executable.

To build the project, first test that you have CMake installed, and if not, install it using the package manager that is used by your flavor of Linux. For example, under Debian:

molloyd@beaglebone:~/$ sudo apt-get install cmake

molloyd@beaglebone:~/$ cmake -version
cmake version 2.8.9

The project code is in the GitHub repository directory, where you will see only the two files described in Listings 1 and 2 above:

molloyd@beaglebone:~$ cd ~/exploringBB/extras/cmake/helloworld/
molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ ls
CMakeLists.txt helloworld.cpp

Now you are ready to build the Hello World project using CMake — execute the cmake command and pass it the directory that contains the source code and the CMakeLists.txt file — in this case “.” refers to the current directory:

molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ cmake .
-- The C compiler identification is GNU 4.6.3
-- The CXX compiler identification is GNU 4.6.3
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/molloyd/exploringBB/extras/cmake/helloworld

CMake identified the environment settings for the Linux device and created the Makefile for this project, which can be viewed. Do not make edits to this Makefile, as any edits will be overwritten the next time that the cmake utility is executed.

molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ ls
CMakeCache.txt CMakeFiles CMakeLists.txt Makefile cmake_install.cmake helloworld.cpp
molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ ls -l Makefile
-rw-r--r-- 1 molloyd molloyd 4811 Apr 1 01:52 Makefile
molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ more Makefile
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8

# The shell in which to execute make rules.
SHELL = /bin/sh

Once the Makefile has been created, the make command can be used to build the project:

molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ make
Scanning dependencies of target hello
[100%] Building CXX object CMakeFiles/hello.dir/helloworld.cpp.o
Linking CXX executable hello
[100%] Built target hello
molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ ls -l hello
-rwxr-xr-x 1 molloyd molloyd 7335 Apr 1 01:54 hello
molloyd@beaglebone:~/exploringBB/extras/cmake/helloworld$ ./hello
Hello World!

It works! However, this process is a somewhat excessive way to just build the HelloWorld.cpp program. It is important though, because it explains the basic operation of CMake. We can now examine more complex CMake examples.

Example 2: A Project with Directories

As your project grows, it is likely that you will organize it into sub-directories. Makefiles become more verbose when there are sub-directories present — in fact, it is usual practice to place an individual Makefile in each sub-directory. These Makefiles are then individually invoked by the Makefile in the parent directory.

CMake can be very useful in this situation. In this example, a project with a typical directory structure is used. The tree utility program displays below the structure of the example project (note: this student test project is available in the GitHub repository that is described above):

molloyd@beaglebone:~/exploringBB/extras/cmake/student$ tree
.
|-- CMakeLists.txt
|-- build
|-- include
| \-- Student.h
\-- src
  |-- Student.cpp
  \-- mainapp.cpp
3 directories, 4 files

You can see in this example that any header files (.h) are placed in the include directory and that the source files (.cpp) are placed in the src directory. I have also created a build directory (which is currently empty) that is used to contain the final binary executable and any temporary files that are required for the build. The CMakeLists.txt file for this project in Listing 3 is only slightly different than that in Listing 2 above:

Listing 3: The Multi-directory Project CMakeLists.txt file

1

2

3

4

5

6

7

8

9

10

11

12

13

cmake_minimum_required(VERSION 2.8.9)

project(directory_test)

#Bring the headers, such as Student.h into the project

include_directories(include)

#Can manually add the sources using the set command as follows:

#set(SOURCES src/mainapp.cpp src/Student.cpp)

#However, the file(GLOB...) allows for wildcard additions:

file(GLOB SOURCES "src/*.cpp")

add_executable(testStudent ${SOURCES})

The important changes in Listing 3 are as follows:

  • The include_directories() function is used to bring the header files into the build environment.
  • The set(SOURCES … ) function can be used to set a variable (SOURCES) that contains the name values of all of the source files (.cpp) in the project. However, because each source file must be added manually the next line is used in its place, and this line is commented out.
  • The file() command is used to add the source files to the project. GLOB (or GLOB_RECURSE) is used to create a list of all of the files that meet the globbing expression (i.e., “src/*.cpp“) and add them to a variable SOURCES.
  • The add_executable() function uses the SOURCES variable, rather than an explicit reference to each source file, in order to build the testStudent executable program.

For this example, I wish to place all of the build files in the build directory, which is achieved very simply by calling the cmake program from within the build directory, as follows:
molloyd@beaglebone:~/exploringBB/extras/cmake/student$ cd build
molloyd@beaglebone:~/exploringBB/extras/cmake/student/build$ cmake ..
-- The C compiler identification is GNU 4.6.3
-- The CXX compiler identification is GNU 4.6.3

-- Build files have been written to: /home/molloyd/exploringBB/extras/cmake/student/build

The build directory then contains the Makefile for the project, which correctly refers to the files in the src and include directories. The project can then be built from the build directory using the make command:

molloyd@beaglebone:~/exploringBB/extras/cmake/student/build$ ls
CMakeCache.txt CMakeFiles Makefile cmake_install.cmake
molloyd@beaglebone:~/exploringBB/extras/cmake/student/build$ make

molloyd@beaglebone:~/exploringBB/extras/cmake/student/build$ ls
CMakeCache.txt CMakeFiles Makefile cmake_install.cmake testStudent
molloyd@beaglebone:~/exploringBB/extras/cmake/student/build$ ./testStudent
A student with name Joe

One nice feature of this approach is that all of the files related to the build process are within the build directory as illustrated by the tree utility output below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

molloyd@beaglebone:~/exploringBB/extras/cmake/student/build$ cd ..

molloyd@beaglebone:~/exploringBB/extras/cmake/student$ tree

.

|-- CMakeLists.txt

|-- build

|   |-- CMakeCache.txt

|   |-- CMakeFiles

|   |   |-- CMakeCCompiler.cmake

|   |   |-- CMakeCXXCompiler.cmake

|   |   |-- CMakeDetermineCompilerABI_C.bin

|   |   |-- CMakeDetermineCompilerABI_CXX.bin

|   |   |-- CMakeDirectoryInformation.cmake

|   |   |-- CMakeOutput.log

|   |   |-- CMakeSystem.cmake

|   |   |-- CMakeTmp

|   |   |-- CompilerIdC

|   |   |   |-- CMakeCCompilerId.c

|   |   |   `-- a.out

|   |   |-- CompilerIdCXX

|   |   |   |-- CMakeCXXCompilerId.cpp

|   |   |   `-- a.out

|   |   |-- Makefile.cmake

|   |   |-- Makefile2

|   |   |-- TargetDirectories.txt

|   |   |-- cmake.check_cache

|   |   |-- progress.marks

|   |   `-- testStudent.dir

|   |       |-- CXX.includecache

|   |       |-- DependInfo.cmake

|   |       |-- build.make

|   |       |-- cmake_clean.cmake

|   |       |-- depend.internal

|   |       |-- depend.make

|   |       |-- flags.make

|   |       |-- link.txt

|   |       |-- progress.make

|   |       `-- src

|   |           |-- Student.cpp.o

|   |           `-- mainapp.cpp.o

|   |-- Makefile

|   |-- cmake_install.cmake

|   `-- testStudent

|-- include

|   `-- Student.h

`-- src

|-- Student.cpp

`-- mainapp.cpp

To clean this project you can simply recursively delete all files/directories within the build directory, for example:
molloyd@beaglebone:~/exploringBB/extras/cmake/student/build$ cd ..
molloyd@beaglebone:~/exploringBB/extras/cmake/student$ rm -r build/*
molloyd@beaglebone:~/exploringBB/extras/cmake/student$ tree

.
|-- CMakeLists.txt
|-- build
|-- include
| \-- Student.h
\-- src
. |-- Student.cpp
. \-- mainapp.cpp
3 directories, 4 files

which is the same file system structure as was present before the cmake program was executed.

Important: If you add new source files to your project it is very important that you call the cmake program again, otherwise the Makefiles will not be updated to account for any additions.

Example 3: Building a Shared Library (.so)

In this example a shared library is built using the project code in Example 2. The project is almost the same, except that the mainapp.cpp file is removed, as it is not relevant to a library build. Therefore, the shared library only contains a single Student class, however, that is sufficient to demonstrate the principles of building a library using CMake. The directory structure of the project is as follows:

molloyd@beaglebone:~/exploringBB/extras/cmake$ tree studentlib_shared/
studentlib_shared/
|-- CMakeLists.txt
|-- build
|-- include
| \-- Student.h
\-- src
. \-- Student.cpp
3 directories, 3 files

Again in this project, header files are placed in the include directory and source files are placed in the src directory. The empty build directory is used to contain the final binary library and any temporary files that are required for the build. The CMakeLists.txt file is provided in Listing 4.

Listing 4: The Multi-directory Shared Library Build CMakeLists.txt file

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

cmake_minimum_required(VERSION 2.8.9)

project(directory_test)

set(CMAKE_BUILD_TYPE Release)

#Bring the headers, such as Student.h into the project

include_directories(include)

#However, the file(GLOB...) allows for wildcard additions:

file(GLOB SOURCES "src/*.cpp")

#Generate the shared library from the sources

add_library(testStudent SHARED ${SOURCES})

#Set the location for library installation -- i.e., /usr/lib in this case

# not really necessary in this example. Use "sudo make install" to apply

install(TARGETS testStudent DESTINATION /usr/lib)

The important changes for this example are as follows:

  • The set(CMAKE_BUILD_TYPE Release) function is used to set the build type to be a release build.
  • Instead of the add_executable() function that is used in previous examples, this example uses the add_library() function. The library is built as a shared library using the SHARED flag (other options are: STATIC or MODULE) , and the testStudent name is used as the name of the shared library.
  • The last line uses the install() function to define an installation location for the library (in this case it is /usr/lib). Deployment is invoked using a call to sudo make install in this case.

In this example the library is built in the build directory, which results in the output:

molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_shared$ cd build/
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_shared/build$ cmake ..
-- The C compiler identification is GNU 4.6.3

molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_shared/build$ make
Scanning dependencies of target testStudent
[100%] Building CXX object CMakeFiles/testStudent.dir/src/Student.cpp.o
Linking CXX shared library libtestStudent.so
[100%] Built target testStudent
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_shared/build$ ls -l *.so
-rwxr-xr-x 1 molloyd molloyd 7503 Apr 1 21:36 libtestStudent.so

You can use the ldd command to display the shared library dependencies:
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_shared/build$ ldd libtestStudent.so
libstdc++.so.6 => /usr/lib/arm-linux-gnueabihf/libstdc++.so.6 (0xb6ea6000)
libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0xb6e3a000)
libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0xb6e16000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6d31000)
/lib/ld-linux-armhf.so.3 (0xb6f6b000)

The CMakeLists.txt file also includes a deployment step, which allows you to install the library in a suitable accessible location. Shared library locations can be added to the path, or if you wish to make them available system wide you can add them to the /usr/lib directory. For example, the libtestStudent.so library can be installed system wide using:

molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_shared/build$ sudo make install
[sudo] password for molloyd:
[100%] Built target testStudent
Install the project…
-- Install configuration: "Release"
-- Installing: /usr/lib/libtestStudent.so
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_shared/build$ ls -l /usr/lib|grep libtest*
-rw-r--r-- 1 root root 7503 Apr 3 14:23 libtestStudent.so

This step has to be performed with root access in order to write to the /usr/lib directory. You will also find a file in the build directory, called install_manifest.txt that describes the locations at which the make install command applied changes.

Example 4: Building a Static Library (.a)

A statically-linked library is created at compile time to contain all of the code code relating the library — essentially it makes copies of any dependency code, including that in other libraries. This results in a library that is typically larger in size than the equivalent shared library, but because all of the dependencies are determined at compile time, there are fewer run-time loading costs and the library may be more platform independent. Unless you are certain that you require a static library, you should use a shared library (Example 3) as there will be fewer code duplications and the shared library can be updated (e.g., for error correction) without recompilation.

To build a static library using CMake, the steps are almost exactly the same as for Example 3 above. The code for this example is available in exploringBB/extras/cmake/studentlib_static/ and the CMakeLists.txt file is provided in Listing 5 below.

Listing 5: The Static Library CMakeLists.txt file

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

cmake_minimum_required(VERSION 2.8.9)

project(directory_test)

set(CMAKE_BUILD_TYPE Release)

#Bring the headers, such as Student.h into the project

include_directories(include)

#However, the file(GLOB...) allows for wildcard additions:

file(GLOB SOURCES "src/*.cpp")

#Generate the static library from the sources

add_library(testStudent STATIC ${SOURCES})

#Set the location for library installation -- i.e., /usr/lib in this case

# not really necessary in this example. Use "sudo make install" to apply

install(TARGETS testStudent DESTINATION /usr/lib)

Use the same steps as before to build the static library, and you will see the output as follows:
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_static$ cd build/
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_static/build$ cmake ..
-- The C compiler identification is GNU 4.6.3

molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_static/build$ make
Scanning dependencies of target testStudent
[100%] Building CXX object CMakeFiles/testStudent.dir/src/Student.cpp.o
Linking CXX static library libtestStudent.a
[100%] Built target testStudent
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_static/build$ ls -l lib*
-rw-r--r-- 1 molloyd molloyd 3320 Mar 2 01:50 libtestStudent.a

You can determine the constituents of a static library using the GNU ar (archive) command — for example:
molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_static/build$ ar -t libtestStudent.a
Student.cpp.o

You can also use the GNU nm command to list the symbols in object files and binaries. In this case, the command lists the symbols in the student library and their types (e.g., T is code, U is undefined, R is read-only data). This information can be very useful for debugging any problems that may occur with static libraries.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

molloyd@beaglebone:~/exploringBB/extras/cmake/studentlib_static/build$ nm -C libtestStudent.a

Student.cpp.o:

00000000 b .LANCHOR1

00000000 t _GLOBAL__sub_I__ZN7StudentC2ESs

00000000 T Student::display()

00000060 T Student::Student(std::string)

00000060 T Student::Student(std::string)

U std::ctype<char>::_M_widen_init() const

U std::ostream::put(char)

U std::ostream::flush()

U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)

U std::ios_base::Init::Init()

U std::ios_base::Init::~Init()

U std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)

U std::__throw_bad_cast()

U std::cout

00000000 b std::__ioinit

00000018 R typeinfo for Student

0000000c R typeinfo name for Student

00000000 R vtable for Student

U vtable for __cxxabiv1::__class_type_info

U __aeabi_atexit

U __aeabi_unwind_cpp_pr0

U __dso_handle

Example 5: Using a Shared or Static Library

Once a library has been developed using the steps described in Example 3 or Example 4, the next question is how do you use the library in your projects? CMake can be used to generate the Makefiles in your project in order to simplify this process.

Listing 6 provides the source code for a CMakeLists.txt file that can be used to build a program that links to a library (either shared or static). For this example the shared library that is generated in Example 3 is used and a short C++ program is written that utilizes the functionality of that library. This C++ code is provided in Listing 7 and in the directory exploringBB/extras/cmake/usestudentlib/.

Listing 6: The CMakeLists.txt file for building a C++ program that uses a library

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

cmake_minimum_required(VERSION 2.8.9)

project (TestLibrary)

#For the shared library:

set ( PROJECT_LINK_LIBS libtestStudent.so )

link_directories( ~/exploringBB/extras/cmake/studentlib_shared/build )

#For the static library:

#set ( PROJECT_LINK_LIBS libtestStudent.a )

#link_directories( ~/exploringBB/extras/cmake/studentlib_static/build )

include_directories(~/exploringBB/extras/cmake/studentlib_shared/include)

add_executable(libtest libtest.cpp)

target_link_libraries(libtest ${PROJECT_LINK_LIBS} )

Listing 7: An Example C++ Program

1

2

3

4

5

6

7

#include"Student.h"

int main(int argc, char *argv[]){

Student s("Joe");

s.display();

return 0;

}

The project can be built and executed using the following steps:

molloyd@beaglebone:~/exploringBB/extras/cmake/usestudentlib$ tree
.
|-- CMakeLists.txt
|-- build
\-- libtest.cpp
1 directory, 2 files
molloyd@beaglebone:~/exploringBB/extras/cmake/usestudentlib$ cd build
molloyd@beaglebone:~/exploringBB/extras/cmake/usestudentlib/build$ cmake ..
-- The C compiler identification is GNU 4.6.3

molloyd@beaglebone:~/exploringBB/extras/cmake/usestudentlib/build$ make
Scanning dependencies of target libtest
[100%] Building CXX object CMakeFiles/libtest.dir/libtest.cpp.o
Linking CXX executable libtest
[100%] Built target libtest
molloyd@beaglebone:~/exploringBB/extras/cmake/usestudentlib/build$ ls -l libtest
-rwxr-xr-x 1 molloyd molloyd 7706 Apr 2 21:07 libtest
molloyd@beaglebone:~/exploringBB/extras/cmake/usestudentlib/build$ ./libtest
A student with name Joe

Conclusions

The examples above provide a short and practical introduction to CMake and how it can be used to build: a simple project, a separately compiled project, and a shared library. These are the operations that you are likely to perform and the examples above can act as templates. However, it is also likely that you will require functionality that is not listed in this short discussion. The best, and most up-to-date documentation on CMake is available at the www.cmake.org website. In particular, the CMake Documentation Index provides a very useful list of available commands. The document is available at: CMake 3.0 Documentation Index

转自:http://derekmolloy.ie/hello-world-introductions-to-cmake/

IEEE、万方文献及国内外专利下载,更多技术文章阅读,请关注微信公众号IEEE

Introduction to CMake by Example相关推荐

  1. 学习C++:C++进阶(三)CMake基础篇---用一个小型项目了解CMake及环境构建

    V1.1 于2022年7月15日第二次修改:添加了比较多的解释图,解读了各类库的CMakelist.txt文件 目录 第一部分 基础篇(Basics) 1.0 本部分主要学什么(Intro) 1.1 ...

  2. 现代 CMake 简明教程(一)- CMake 基础

    系列文章目录 现代 CMake 简明教程(一)- CMake 基础 现代 CMake 简明教程(二)- 设计理念与使用 文章目录 系列文章目录 前言 CMake 基础 1. Modern CMake ...

  3. AN INTRODUCTION TO MOOS

    GTRI ROBOLAB也在用MOOS-IvP,这是他们网站上的一篇介绍文章,和我的前一篇文章内容相似. The Mission Oriented Operating Suite (MOOS) is ...

  4. 使用CMake构建/开始使用CMake

    Getting started with CMake 开始使用CMake CMake is a group of tools that allow to build, test, and packag ...

  5. cmake+opencv4.1+opencv_contrib4.1+CUDA以及CUDA11.x的NPP新模块watershedSegmentation

    一.环境配置 1.网上很多教程都有,安装合适自己电脑的CUDA,我已安装完毕 2.CMake编译opencv4.1+opencv_contrib4.1+CUDA,网上依旧很多教程.我前几次编译时,遇到 ...

  6. TVM cmake示例展示

    TVM cmake示例展示 本文展示tvm/cmake中config.cmake,tvm/cmake/module/LLVM.cmake,tvm/cmake/module/CUDA.cmake,tvm ...

  7. VScode配置CMAKE文件

    创建一个vscode文件 记得一定要创建一个build文件夹,因为cmake编译过程中产生的中间文件会放到build文件夹中. 打开VScode 配置文件 launch.json {"ver ...

  8. PCL1.9的PCLConfig.cmake文件找不到eigen等外部依赖

    PCL1.9的PCLConfig.cmake文件找不到eigen等外部依赖 由于需要用到PCL中on_nurbs模块做拟合,但是ros自带的pcl中没有该模块.所以源码安装了PCL 1.9,但是在使用 ...

  9. ++项目 cmake头文件路径_CMAKE入门实战

    0.导语 最近做的项目使用CLION构建,而这个采用CMakeLists.txt管理,因此为了更好的学习,故找到了一篇大牛级别的入门文章,有文章有代码,本文是花了一点时间把这篇文章学习后的重要点记录吧 ...

最新文章

  1. Linux下分割与合并文件的方法
  2. 计算机电缆外径相差太大,DJYPVP计算机电缆标准外径
  3. 中澜视讯产品运营总监黄超强:产品+付费+未来汽车
  4. Java建造者模式详解
  5. linux磁盘空间回收,linux磁盘空间满了后怎么去判定哪个地方占了多大的空间并回收...
  6. nginx ngx_http_proxy_module(反向代理)
  7. 错误 -source 1.6 中不支持 diamond 运算符的解决办法(已解决)
  8. 从留言簿开始,学习MonoRail MVC(三)
  9. 刷网课-踩坑——jsDOM获取不到页面元素节点-iframe标签获取元素节点
  10. 思科模拟器-实验 18 三层交换访问控制列表配置
  11. 文件上传 webshell 各类型 一句话木马 图片马 制作 教程
  12. android 向上滑动home,滑动Home键
  13. java毕业设计的健身俱乐部综合管理系统mybatis+源码+调试部署+系统+数据库+lw
  14. Kernel panic - not syncing VFS Unable to mount root fs on
  15. MIC(最大信息系数)
  16. 二次型,标准型,规范型
  17. 企业中Linux下软件的管理(yum仓库的搭建以及软件的控制)
  18. MOOSE多物理场耦合平台入门学习记录一(稳态热传导程序实例)
  19. 单价数量和总价的公式_知道总价和数量怎么算单价
  20. 计算机科学与技术考研双非,这几所双非院校,考研难度堪比985,211!

热门文章

  1. 软件测试-柠檬班python全栈自动化50期测试学习笔记分享
  2. 【perl计算基因在基因组上的距离】
  3. Java中识别二维码并且提高二维码的识别率
  4. Java内存大小换算
  5. AT4896 [ABC161C] Replacing Integer
  6. 一文读懂 Java 反射机制那些事
  7. Mathmatica中的Sum命令
  8. 没噪音免更换滤网?贝昂JY200净化器评测
  9. 室内定位技术之UWB篇
  10. 电脑重装系统后序列号怎么查