本文目标

  1. 使用 python 写一个管理 cmake 工程的 cli 程序

代码地址

https://gitcode.net/u014254963/cm_cli

参考

python Click 官网

Click 中文文档

argparse 文档

使用说明

  • 详细说明

思路

使用 click 制作单独的命令, 比如 mcmake_inti,mcmake_built , 每一个命令都打包为单独的可执行文件
然后用argparse制作一个调度的可执行文件
直接用标准库的 argparse 即可

一个 click 的 Hello World

文件列表

mcmake.py: 命令入口
mcmake_init.py: 初始化项目
mcmake_build.py: 构建

源码

mcmake_init.py

# -*- coding: utf-8 -*-

import click


@click.command()
@click.option('--init', help='初始化项目', nargs=0)
@click.option('--language', type=click.Choice(['c', 'c++']), prompt='选择语言', help='选择语言')
def init(init, language):
    click.echo('初始化项目')
    click.echo('language: %s' % language)


if __name__ == '__main__':
    init()

mcmake_build.py

# -*- coding: utf-8 -*-

import click


@click.command()
@click.option('--build', help='初始化项目', nargs=0)
@click.option('--config', type=click.Choice(['debug', 'release']), default='debug', prompt='构建类型', help='构建类型')
def build(build, config):
    click.echo('初始化项目')
    click.echo('config: %s' % config)


if __name__ == '__main__':
    build()

mcmake.py

# -*- coding: utf-8 -*-

import argparse
import os

parser = argparse.ArgumentParser()
parser.add_argument('init', help='初始化项目', nargs='?', const='1')
parser.add_argument('build', help='构建项目', nargs='?', const='2')
parser.add_argument('help', help='显示帮助', nargs='?', const='3')

args = parser.parse_args()
if __name__ == '__main__':
    if 'init' == args.init:
        os.system('mcmake_init')
    elif 'build' == args.init:
        os.system('mcmake_build')
    elif 'help' == args.init:
        os.system('mcmake_init --help')
        os.system('mcmake_build --help')

打包

分别打包三个文件

# 打包 mcmake 调度命令
pyinstaller -F mcmake.py
pyinstaller mcmake.spec

# 打包 mcmake 初始化命令
pyinstaller -F mcmake_init.py
pyinstaller mcmake_init.spec

# 打包 mcmake_build 构建命令
pyinstaller -F mcmake_build.py
pyinstaller mcmake_build.spec

此时打包在了 ./dist 目录中

window验证

(venv) F:\2023\code\cmake\cm-cli\dist>dir
 驱动器 F 中的卷是 dox
 卷的序列号是 34D2-6BE8

 F:\2023\code\cmake\cm-cli\dist 的目录

2023/01/23  02:55    <DIR>          .
2023/01/23  02:55    <DIR>          ..
2023/01/23  02:55         6,622,500 mcmake.exe
2023/01/23  02:46         6,903,074 mcmake_build.exe
2023/01/23  02:45         6,903,056 mcmake_init.exe
               3 个文件     20,428,630 字节
               2 个目录 92,017,352,704 可用字节

(venv) F:\2023\code\cmake\cm-cli\dist>mcmake --help
usage: mcmake [-h] [init] [build] [help]

positional arguments:
  init        初始化项目
  build       构建项目
  help        显示帮助

options:
  -h, --help  show this help message and exit

(venv) F:\2023\code\cmake\cm-cli\dist>mcmake help
Usage: mcmake_init [OPTIONS]

Options:
  --init TEXT...      初始化项目
  --language [c|c++]  选择语言
  --help              Show this message and exit.
Usage: mcmake_build [OPTIONS]

Options:
  --build TEXT...           初始化项目
  --config [debug|release]  构建类型
  --help                    Show this message and exit.

(venv) F:\2023\code\cmake\cm-cli\dist>mcmake init
选择语言 (c, c++): c++
初始化项目
language: c++

(venv) F:\2023\code\cmake\cm-cli\dist>mcmake build
构建类型 (debug, release) [debug]:
初始化项目
config: debug

(venv) F:\2023\code\cmake\cm-cli\dist>mcmake_init
选择语言 (c, c++): c++
初始化项目
language: c++

(venv) F:\2023\code\cmake\cm-cli\dist>mcmake_init --language=java
Usage: mcmake_init [OPTIONS]
Try 'mcmake_init --help' for help.

Error: Invalid value for '--language': 'java' is not one of 'c', 'c++'.

(venv) F:\2023\code\cmake\cm-cli\dist>mcmake_init --language=c++
初始化项目
language: c++

(venv) F:\2023\code\cmake\cm-cli\dist>

然后把 dist 目录添加到环境变量再次验证

C:\Users\laolang>where mcmake
F:\2023\code\cmake\cm-cli\dist\mcmake.exe

C:\Users\laolang>mcmake --help
usage: mcmake [-h] [init] [build] [help]

positional arguments:
  init        初始化项目
  build       构建项目
  help        显示帮助

options:
  -h, --help  show this help message and exit

C:\Users\laolang>mcmake init
选择语言 (c, c++): c++
初始化项目
language: c++

C:\Users\laolang>

linux 验证

注意: linux 需要把可执行文件所在目录添加到 .bashrc 才可以

ubuntu@ubuntu-cpp:~$ mcmake --help
usage: mcmake [-h] [init] [build] [help]

positional arguments:
  init        初始化项目
  build       构建项目
  help        显示帮助

options:
  -h, --help  show this help message and exit
ubuntu@ubuntu-cpp:~$ mcmake init
选择语言 (c, c++): c++
初始化项目
language: c++
ubuntu@ubuntu-cpp:~$ mcmake debug
ubuntu@ubuntu-cpp:~$ mcmake build
构建类型 (debug, release) [debug]: 
初始化项目
config: debug
ubuntu@ubuntu-cpp:~$

正式开发前的准备

检查环境变量

上面的 Hello World 中调度命令为 mcmake, 本来想设置成cm的, 但是我的电脑上已经有了这个命令了

C:\Users\laolang>where cm
C:\Program Files\PlasticSCM5\client\cm.exe

C:\Users\laolang>

解决办法就是把环境变量的顺序调整一下

功能点描述

要求

无侵入. 即便脱离 cm-cli , 也不能影响cmake工程的构建流程

命令是怎样用的

调度命令

选项

含义

init

初始化项目

build

构建项目

run

运行

test

运行测试

doxygen

生成 doxygen 文档

init 子命令

选项

含义

--name

项目名称

--language

语言. 可选项: c, c++

--standard

语言标准, 目前的标准: c(89,90,99,11,18) , c++(98,11,14,17,20,23). c语言默认为11, c++默认为14

--type

项目类型. simple(单目录) , simple_app(多目录, 一个include, 一个src) , module_app(多目录, src和include下添加子目录. src 下每个子目录编译为静态库或动态库. 默认为动态库, 可单独配置) 默认为 simple_app

--build-dir

构建目录. 默认为 build

--output-dir

二进制或库文件输出目录. 默认为 bin


build 子命令

选项

含义

--type

构建类型. debug 或 release . 默认为 debug

目录结构

ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ tree -a
	.
cm目录, 类似 .git 目录		├── .cm
钩子脚本所在目录			│   ├── hooks
构建后运行的脚本			│   │   ├── post-build-sample.py
运行后运行的脚本			│   │   ├── post-run-sample.py
测试后运行的脚本			│   │   ├── post-test-sample.py
构建前运行的脚本			│   │   ├── pre-build-sampel.py
运行前运行的脚本			│   │   ├── pre-run-sample.py
测试前运行的脚本			│   │   └── pre-test-sample.py
日志						│   └── logs
顶层 CMakeLists.txt			├── CMakeLists.txt
doxygen 配置文件			├── Doxyfile
二进制或库文件所在目录		├── bin
构建目录					├── build
cm 配置文件					├── cm.json
doxygen 生成文档所在目录	├── doc
							├── include
第三方库目录				├── libs
							├── readme.md
							├── src
第三方库源码				└── third

10 directories, 10 files
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$

帮助文档

使用 VuePress 写出完整帮助文档

cmake 项目的准备

不考虑 32位
暂时没有处理 msvc , vs , MinGW
未展示 C 语言项目 , 但是结构都差不多

要求

  1. 要在windows上测试 mingw , tdm-gcc , msvc 只测试了 tdm-gcc
  2. 要在 vscode 和 vs 分别测试
  3. linux也要测试
  4. cmake 脚本尽量简洁

simple

目录结构

F:\2023\code\cmake\cm_cli_proj\simple_cpp>tree /f
卷 dox 的文件夹 PATH 列表
卷序列号为 34D2-6BE8
F:.
    CMakeLists.txt
    main.cpp

没有子文件夹


F:\2023\code\cmake\cm_cli_proj\simple_cpp>

c++ 源码

main.cpp

#include <iostream>
int main()
{
    std::cout << "Hello World!" << std::endl;
    return 0;
}

CMakeLists.txt

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project($%{proj_name} CXX)

# 指定语言标准
set(CMAKE_CXX_STANDARD $%{standard})
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 参与编译的源文件列表
aux_source_directory(. MAIN_SRCS)

# 可执行文件所在目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/$%{output_dir})


add_executable(${PROJECT_NAME} ${MAIN_SRCS})

simple_app

目录结构

F:\2023\code\cmake\cm_cli_proj\simple_app_cpp>tree /f
卷 dox 的文件夹 PATH 列表
卷序列号为 34D2-6BE8
F:.
│  CMakeLists.txt
│
├─include
│      sample.h
│
└─src
        CMakeLists.txt
        main.cpp
        sample.cpp


F:\2023\code\cmake\cm_cli_proj\simple_app_cpp>

c++ 源码

sample.h

#ifndef _SAMPLE_H_
#define _SAMPLE_H_

int add(int x, int y);

#endif // _SAMPLE_H_

src/sample.cpp

#include "sample.h"

int add(int x, int y)
{
    return x + y;
}

src/main.cpp

#include <iostream>

#include "sample.h"

int main()
{
    std::cout << "1 + 2 = " << add(1,2) << std::endl;
    std::cout << "Hello World!" << std::endl;
    return 0;
}

CMakeLists.txt

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(one CXX)

# 指定语言标准
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_subdirectory(src)

src/CMakeLists.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. SRCS)

# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${SRCS})

module_app

目录结构

F:\2023\code\cmake\cm_cli_proj\module_app_cpp>tree /f
卷 dox 的文件夹 PATH 列表
卷序列号为 34D2-6BE8
F:.
│  CMakeLists.txt
│
├─include
│  └─sample
│          sample.h
│
└─src
    │  CMakeLists.txt
    │
    ├─main
    │      CMakeLists.txt
    │      main.cpp
    │
    └─sample
            CMakeLists.txt
            sample.cpp


F:\2023\code\cmake\cm_cli_proj\module_app_cpp>

c++ 源码

include/sample.h

#ifndef _SAMPLE_H_
#define _SAMPLE_H_

int add(int x, int y);

#endif // _SAMPLE_H_

src/sample/sample.cpp

#include "sample/sample.h"

int add(int x, int y)
{
    return x + y;
}

src/main/main.cpp

#include <iostream>

#include "sample/sample.h"

int main()
{
    std::cout << "1 + 2 = " << add(1,2) << std::endl;
    std::cout << "Hello World!" << std::endl;
    return 0;
}

CMakeLists.txt

CMakeLists.txt

# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(one CXX)

# 指定 语言标准
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(lib_sample sample)

add_subdirectory(src)

src/CMakeLists.txt

add_subdirectory(main)
add_subdirectory(sample)

src/main/CMakeLists.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. MAIN_SRCS)

# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${MAIN_SRCS})

# 声明链接时需要参与的依赖库名称
target_link_libraries(${PROJECT_NAME} ${lib_sample})

src/sample/CMakeLists.txt

# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. SAMPLE_SRCS)

# 设置生成目录
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 生成库
add_library(${lib_sample} SHARED ${SAMPLE_SRCS})

# 指定动态库版本
# VERSION 动态库版本
# SOVERSION API版本
set_target_properties(${lib_sample} PROPERTIES VERSION 1.0 SOVERSION 1)

cm_cli 的测试

不展示 windows
代码地址: https://gitcode.net/u014254963/cm_cli

一个 最小化demo

# -*- coding: utf-8 -*-
import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

# 每个子命令都要添加这个参数, 用于区分当前运行的是哪个子命令
KEY_CM_ACTION = 'cm_action'
ARG_PREFIX = '--'

SUB_COMMAND_INIT = 'init'
ARG_INIT_NAME = 'name'
ARG_INIT_LANGUAGE = 'language'

SUB_COMMAND_BUILD = 'build'
ARG_BUILD_RE = 're'

d = {
    'init':{
        'name': False,
        'language': False
    }
}

class InitNameAction(argparse.Action):
    """
    自定义 action
    """

    def __init__(self, option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None,
                 required=False, help=None, metavar=None):
        super().__init__(option_strings, dest, nargs, const, default, type, choices, required, help, metavar)

    def init_config(self):
        pass

    def valid_arg(self, values):
        pass

    def _get_kwargs(self):
        names = [
            'option_strings',
            'dest',
            'nargs',
            'const',
            'default',
            'type',
            'choices',
            'help',
            'metavar',
        ]
        return [(name, getattr(self, name)) for name in names]

    def format_usage(self):
        return self.option_strings[0]

    def __call__(self, parser, namespace, values, option_string=None):
        print('某些处理. 通常是保存参数值或者做某些检查')
        d['init']['name'] = True
        setattr(namespace, self.dest, values)

class InitLanguageAction(argparse.Action):
    """
    自定义 action
    """

    def __init__(self, option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None,
                 required=False, help=None, metavar=None):
        super().__init__(option_strings, dest, nargs, const, default, type, choices, required, help, metavar)

    def init_config(self):
        pass

    def valid_arg(self, values):
        pass

    def _get_kwargs(self):
        names = [
            'option_strings',
            'dest',
            'nargs',
            'const',
            'default',
            'type',
            'choices',
            'help',
            'metavar',
        ]
        return [(name, getattr(self, name)) for name in names]

    def format_usage(self):
        return self.option_strings[0]

    def __call__(self, parser, namespace, values, option_string=None):
        print('某些处理. 通常是保存参数值或者做某些检查')
        d['init']['language'] = True
        setattr(namespace, self.dest, values)


def register_init_args():
    """
    注册 init 子命令
    """
    init_parsers = subparsers.add_parser(SUB_COMMAND_INIT, help='初始化')
    init_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_INIT)
    init_parsers.add_argument(ARG_PREFIX + ARG_INIT_NAME, help='项目名称', action=InitNameAction)
    init_parsers.add_argument(ARG_PREFIX + ARG_INIT_LANGUAGE, help='语言', choices=['c', 'cpp'],
                              action=InitLanguageAction)

def register_build_args():
    """
    注册 build 子命令
    """
    build_parsers = subparsers.add_parser(SUB_COMMAND_BUILD, help='构建')
    build_parsers.add_argument(ARG_PREFIX + KEY_CM_ACTION, help='动作类型', default=SUB_COMMAND_BUILD)


def collec_init_data():
    while not d['init']['name']:
        val = input('项目名称:')
        if 0 != len(val):
            d['init']['name'] = True
            # 某些操作
            pass

    while not d['init']['language']:
        val = input('语言标准:')
        if 0 != len(val):
            d['init']['language'] = True
            # 某些操作
            pass


if __name__ == '__main__':
    # 注册命令
    register_init_args()
    register_build_args()

    args = parser.parse_args()
    if SUB_COMMAND_INIT == args.__dict__[KEY_CM_ACTION]:
        collec_init_data()
        print('进行初始化操作')
    elif SUB_COMMAND_BUILD == args.__dict__[KEY_CM_ACTION]:
        print('进行构建操作')

    print(args)

测试

(venv) F:\2023\blog_code\cm_cli>python cm_test.py init --language=c
某些处理. 通常是保存参数值或者做某些检查
项目名称:one
进行初始化操作
Namespace(cm_action='init', name=None, language='c')

(venv) F:\2023\blog_code\cm_cli>python cm_test.py build
进行构建操作
Namespace(cm_action='build')

(venv) F:\2023\blog_code\cm_cli>

基本思路

  1. 添加一个全局的配置单例, 用于保存各种配置, 并且要保存各个子命令的参数是否已设置过
  2. 匹配 KEY_CM_ACTION 后, 检查全局配置中子命令所有参数的状态, 再次收集未配置过的参数
  3. 收集完所有参数, 开始根据子命令的参数进行处理

simple 测试

ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ pwd
/home/ubuntu/code/cmake/cm_test
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm init
项目名称:one
语言(c,cpp):cpp
语言标准(98,11,14,17,20,23,) [14]:
项目类型(simple,simple_app,module_app) [simple_app]:simple
构建目录 [build]:
二进制或库文件输出目录 [bin]:
执行初始化...
文件处理中: /home/ubuntu/code/cmake/cm_test/CMakeLists.txt
初始化完成. 使用 cm build 编译 , cm run 运行
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ tree -a
.
├── CMakeLists.txt
├── cm.json
└── main.cpp

0 directories, 3 files
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cat -n CMakeLists.txt 
     1	cmake_minimum_required(VERSION 3.0)
     2	
     3	# 设置项目名称和语言
     4	project(one CXX)
     5	
     6	# 指定语言标准
     7	set(CMAKE_CXX_STANDARD 14)
     8	set(CMAKE_CXX_STANDARD_REQUIRED True)
     9	
    10	# 参与编译的源文件列表
    11	aux_source_directory(. MAIN_SRCS)
    12	
    13	# 可执行文件所在目录
    14	set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
    15	
    16	
    17	add_executable(${PROJECT_NAME} ${MAIN_SRCS})
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm build
开始构建...
构建命令: cmake -S . -G "Unix Makefiles" -B build && cmake --build build
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/code/cmake/cm_test/build
[ 50%] Building CXX object CMakeFiles/one.dir/main.cpp.o
[100%] Linking CXX executable /home/ubuntu/code/cmake/cm_test/bin/one
[100%] Built target one
构建完成. 使用 cm run 运行
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ ll bin
total 28
drwxrwxr-x 2 ubuntu ubuntu  4096 Jan 24 21:20 ./
drwxrwxr-x 4 ubuntu ubuntu  4096 Jan 24 21:20 ../
-rwxrwxr-x 1 ubuntu ubuntu 16576 Jan 24 21:20 one*
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm run
开始运行...

Hello World!

运行完毕
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$

simple_app 测试

ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ pwd
/home/ubuntu/code/cmake/cm_test
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm init
项目名称:one
语言(c,cpp):cpp
语言标准(98,11,14,17,20,23,) [14]:
项目类型(simple,simple_app,module_app) [simple_app]:
构建目录 [build]:
二进制或库文件输出目录 [bin]:
执行初始化...
文件处理中: /home/ubuntu/code/cmake/cm_test/CMakeLists.txt
文件处理中: /home/ubuntu/code/cmake/cm_test/src/CMakeLists.txt
初始化完成. 使用 cm build 编译 , cm run 运行
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ tree -a
.
├── CMakeLists.txt
├── cm.json
├── include
│   └── sample.h
└── src
    ├── CMakeLists.txt
    ├── main.cpp
    └── sample.cpp

2 directories, 6 files
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cat CMakeLists.txt 
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(one CXX)

# 指定语言标准
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_subdirectory(src)
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cat src/CMakeLists.txt 
# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. SRCS)

# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${SRCS})ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ 
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm build
开始构建...
构建命令: cmake -S . -G "Unix Makefiles" -B build && cmake --build build
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/code/cmake/cm_test/build
[ 33%] Building CXX object src/CMakeFiles/one.dir/main.cpp.o
[ 66%] Building CXX object src/CMakeFiles/one.dir/sample.cpp.o
[100%] Linking CXX executable /home/ubuntu/code/cmake/cm_test/bin/one
[100%] Built target one
构建完成. 使用 cm run 运行
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ ll bin/
total 28
drwxrwxr-x 2 ubuntu ubuntu  4096 Jan 24 21:21 ./
drwxrwxr-x 6 ubuntu ubuntu  4096 Jan 24 21:21 ../
-rwxrwxr-x 1 ubuntu ubuntu 16688 Jan 24 21:21 one*
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm run
开始运行...

1 + 2 = 3
Hello World!

运行完毕
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$

module_app 测试

ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ pwd
/home/ubuntu/code/cmake/cm_test
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm init
项目名称:one
语言(c,cpp):cpp
语言标准(98,11,14,17,20,23,) [14]:
项目类型(simple,simple_app,module_app) [simple_app]:module_app
构建目录 [build]:
二进制或库文件输出目录 [bin]:
执行初始化...
文件处理中: /home/ubuntu/code/cmake/cm_test/CMakeLists.txt
文件处理中: /home/ubuntu/code/cmake/cm_test/src/main/CMakeLists.txt
文件处理中: /home/ubuntu/code/cmake/cm_test/src/sample/CMakeLists.txt
初始化完成. 使用 cm build 编译 , cm run 运行
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ tree -a
.
├── CMakeLists.txt
├── cm.json
├── include
│   └── sample
│       └── sample.h
└── src
    ├── CMakeLists.txt
    ├── main
    │   ├── CMakeLists.txt
    │   └── main.cpp
    └── sample
        ├── CMakeLists.txt
        └── sample.cpp

5 directories, 8 files
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cat CMakeLists.txt 
# 该项目所需 cmake 的最小版本, 如果 cmake 版本小于设置的版本,  cmake 将停止处理并报错
cmake_minimum_required(VERSION 3.0)

# 设置项目名称和语言
project(one CXX)

# 指定 语言标准
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)

set(lib_sample sample)

add_subdirectory(src)
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cat src/main/CMakeLists.txt 
# 头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 源文件列表
aux_source_directory(. MAIN_SRCS)

# 可执行文件目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 使用指定的源文件向项目添加可执行文件
add_executable(${PROJECT_NAME} ${MAIN_SRCS})

# 声明链接时需要参与的依赖库名称
target_link_libraries(${PROJECT_NAME} ${lib_sample})ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ 
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm build
开始构建...
构建命令: cmake -S . -G "Unix Makefiles" -B build && cmake --build build
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/code/cmake/cm_test/build
[ 25%] Building CXX object src/sample/CMakeFiles/sample.dir/sample.cpp.o
[ 50%] Linking CXX shared library /home/ubuntu/code/cmake/cm_test/bin/libsample.so
[ 50%] Built target sample
[ 75%] Building CXX object src/main/CMakeFiles/one.dir/main.cpp.o
[100%] Linking CXX executable /home/ubuntu/code/cmake/cm_test/bin/one
[100%] Built target one
构建完成. 使用 cm run 运行
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ ll bin
total 44
drwxrwxr-x 2 ubuntu ubuntu  4096 Jan 24 21:23 ./
drwxrwxr-x 6 ubuntu ubuntu  4096 Jan 24 21:23 ../
lrwxrwxrwx 1 ubuntu ubuntu    14 Jan 24 21:23 libsample.so -> libsample.so.1*
lrwxrwxrwx 1 ubuntu ubuntu    16 Jan 24 21:23 libsample.so.1 -> libsample.so.1.0*
-rwxrwxr-x 1 ubuntu ubuntu 15136 Jan 24 21:23 libsample.so.1.0*
-rwxrwxr-x 1 ubuntu ubuntu 16656 Jan 24 21:23 one*
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$ cm run
开始运行...

1 + 2 = 3
Hello World!

运行完毕
ubuntu@ubuntu-cpp:~/code/cmake/cm_test$

上述操作有什么问题

  1. 帮助文档的输出是个问题, 理想的帮助文档应当是下面这样的.
F:\code>cm --help
init		初始化
	--language	 	语言: java,c,c++
	--name			项目名称
build		构建
	--type			投建类型: debug, release

--hlep		帮助
F:\code>
  1. 命令别名功能未实现, 目前好像也没啥实现的必要. 这个功能主要是将一些长命令缩短, 比如:
# 设置别名
cm config alias.msvc='cm build -g=Ninja type=Debug install_prefix=/install cxx_complier=/cl.exe make_program=ninja'
# 使用
cm msvc
  1. 类似 git 一样, 区分全局配置与当前项目配置
  2. 需要添加语言标准检测. 简单来说, 就是提前准备好几个特定的程序, 针对不同的标准进行验证.
  3. 应当考虑第三方库
  4. 未实现 testdoxygen 命令