CMake实战
CMake实战
1. Preface
通过CMake来实际构建一个项目,掌握cmake的使用流程;在之前的博客!《CMake学习记录》中,介绍了Cmake相关的基础知识;
2. 需要注意的问题
- 程序版本信息设置,包括编译时间设置
- 指定编译时的编译器
- 编译选项设置
3. 一个简单的Hello world项目
整个项目包含三个文件夹,一个main文件夹,一个para文件夹,一个calc文件夹;
目录结构如下所示:
3.1 根目录下:
CMakeLists.txt文件
# cmake最小版本3.1
cmake_minimum_required(VERSION 3.1)
# 指定编译器的语句需要放在project之前
if(WIN32)
# 需要在运行cmake命令是添加 -G "MinGW Makefiles"选项,则会将编译器默认切换为GUN g++, 否则不生效
set(CMAKE_C_COMPILER D:/software/mingw64/bin/gcc.exe)
set(CMAKE_CXX_COMPILER D:/software/mingw64/bin/g++.exe) # cmake要求路径使用 /
endif(WIN32)
project(CalcDemon VERSION 1.2.4 LANGUAGES CXX C)
# 给定程序的编译时间
string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)
configure_file(./CalcDemonConfig.h.in config.h)
# 设置编译参数
if(WIN32)
# add_complie_options 对所有编译器生效 / 作用域为全局,对子工程的编译也生效
# 根据实践,设置-Werror开启的时候,出现unused variable的时候会报错
# -Wextra开启的话,如果函数定义时是三个参数,实际函数内部只用到两个,编译器就会给出提示
add_compile_options(-Wall -std=c++11)
# CMAKE_CXX_FLAGS 仅仅对C++编译器生效
#set(CMAKE_CXX_FLAGS -std=c++11 -Wall)
endif(WIN32)
# 设置编译类型 debug release
set(CMAKE_BUILD_TYPE RelWithDebInfo)
# 设置必须支持c++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
# 构建子目录
add_subdirectory(./calc ./calc_build)
# 构建子目录
add_subdirectory(./para ./para_build)
# 构建子目录 构建子目录的时候,需要指定子目录 和构建的输出目录
# 注意:子目录构建的输出目录,是相对于当前cmakelists.txt文件的输出目录的
# 也即 ./mian构建的输出目录是相对于当前文件的目录 build/main_build
add_subdirectory(./main ./main_build)
CalcDemonConfig.h.in文件:
// define the configured options and settings
#define PROGRAM_NAME "@PROJECT_NAME@"
#define PROGRAM_VER "@PROJECT_VERSION@"
#define PROGRAM_VER_MAJOR "@PROJECT_VERSION_MAJOR@"
#define PROGRAM_VER_MINOR "@PROJECT_VERSION_MINOR@"
#define PROGRAM_VER_PATCH "@PROJECT_VERSION_PATCH@"
// 编译时间
// 需要在cmakelists.txt文件中写入string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)
#define PROGRAM_COMPILE_TIMESTAMP "@COMPILE_TIME@"
3.2 calc目录
CMakeLists.txt文件,将calc目录下的源码编译为动态库:
# 定义makefile文件
# 导出为库
add_definitions(-DSIMPLE_EXPORT) # 定义宏
#add_definitions(-DSIMPLE_EXPORT=0) # 定义有值的宏
# file命令主要用于文件操作,包括读写,创建,匹配(GLOB)
file(GLOB SRC_FILE_LST ./source/*.cpp)
add_library(simpleCal SHARED ${SRC_FILE_LST})
target_include_directories(simpleCal PUBLIC ./include)
message(STATUS "Generating lib simpleCal.")
simpleexportdef.h目录中定义导出符号:
#ifndef SIMPLE_EXPORT_DEF
#define SIMPLE_EXPORT_DEF
#if defined(WIN32)
#ifdef SIMPLE_EXPORT
#define SIMPLE_LIB_EXPORT __declspec(dllexport)
#else
#define SIMPLE_LIB_EXPORT __declspec(dllimport)
#endif
#else
#define SIMPLE_LIB_EXPORT
#endif
#endif
add.h头文件定义add函数:
#ifndef ADD_H
#define ADD_H
#include "simpleexportdef.h"
int SIMPLE_LIB_EXPORT addS(int x1, int x2);
#endif
add.cpp文件实现add函数:
#include "add.h"
int addS(int x1, int x2)
{
int sum = 0;
sum = x1 + x2;
return sum;
}
div.h头文件定义div函数:
#ifndef DIV_H
#define DIV_H
#include "simpleexportdef.h"
int SIMPLE_LIB_EXPORT divdS(int x1, int x2);
#endif
div.cpp文件实现div函数
#include "div.h"
int divdS(int x1, int x2)
{
int res = 0;
if (x2 == 0)
return res;
res = x1 / x2;
return res;
}
mul.h头文件定义mul函数:
#ifndef MUL_H
#define MUL_H
#include "simpleexportdef.h"
int SIMPLE_LIB_EXPORT mul(int x1, int x2);
#endif
mul.cpp函数实现mul函数:
#include "mul.h"
int mul(int x1, int x2)
{
int res = 0;
res = x1 * x2;
return res;
}
subtract.h头文件定义subtract函数
#ifndef SUBTRACT_H
#define SUBTRACT_H
#include "simpleexportdef.h"
int SIMPLE_LIB_EXPORT substract(int x1, int x2);
#endif
subtract.h文件实现subtract函数
#include "substract.h"
int substract(int x1, int x2)
{
int res = 0;
res = x1 - x2;
return res;
}
3.3 para目录
CMakeLists.txt文件,将para目录下的源码编译为动态库:
# 定义makefile文件
# 导出为库
add_definitions(-DEXPORTS_GETOPT) # 定义宏
#add_definitions(-DSIMPLE_EXPORT=0) # 定义有值的宏
# file命令主要用于文件操作,包括读写,创建,匹配(GLOB)
file(GLOB SRC_FILE_LST ./source/*.cpp)
add_library(getopt SHARED ${SRC_FILE_LST})
target_include_directories(getopt PUBLIC ./include)
message(STATUS "Generating lib getopt.")
getopt.h头文件定义getopt函数:
# ifndef __GETOPT_H_
# define __GETOPT_H_
# ifdef _GETOPT_API
# undef _GETOPT_API
# endif
//------------------------------------------------------------------------------
# if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT)
# error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT \
can only be used individually"
# elif defined(STATIC_GETOPT)
# pragma message("Warning static builds of getopt violate the Lesser GNU \
Public License")
# define _GETOPT_API
# elif defined(EXPORTS_GETOPT)
# pragma message("Exporting getopt library")
# define _GETOPT_API __declspec(dllexport)
# else
# pragma message("Importing getopt library")
# define _GETOPT_API __declspec(dllimport)
# endif
# include <tchar.h>
// Standard GNU options
# define null_argument 0 /*Argument Null*/
# define no_argument 0 /*Argument Switch Only*/
# define required_argument 1 /*Argument Required*/
# define optional_argument 2 /*Argument Optional*/
// Shorter Versions of options
# define ARG_NULL 0 /*Argument Null*/
# define ARG_NONE 0 /*Argument Switch Only*/
# define ARG_REQ 1 /*Argument Required*/
# define ARG_OPT 2 /*Argument Optional*/
// Change behavior for C\C++
# ifdef __cplusplus
# define _BEGIN_EXTERN_C extern "C" {
# define _END_EXTERN_C }
# define _GETOPT_THROW throw()
# else
# define _BEGIN_EXTERN_C
# define _END_EXTERN_C
# define _GETOPT_THROW
# endif
_BEGIN_EXTERN_C
extern _GETOPT_API TCHAR *optarg;
extern _GETOPT_API int optind;
extern _GETOPT_API int opterr;
extern _GETOPT_API int optopt;
struct option
{
/* The predefined macro variable __STDC__ is defined for C++, and it has the in-
teger value 0 when it is used in an #if statement, indicating that the C++ l-
anguage is not a proper superset of C, and that the compiler does not confor-
m to C. In C, __STDC__ has the integer value 1. */
# if defined (__STDC__) && __STDC__
const TCHAR* name;
# else
TCHAR* name;
# endif
int has_arg;
int *flag;
TCHAR val;
};
extern _GETOPT_API int getopt( int argc, TCHAR *const *argv
, const TCHAR *optstring ) _GETOPT_THROW;
extern _GETOPT_API int getopt_long
( int ___argc, TCHAR *const *___argv
, const TCHAR *__shortopts
, const struct option *__longopts
, int *__longind ) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_only
( int ___argc, TCHAR *const *___argv
, const TCHAR *__shortopts
, const struct option *__longopts
, int *__longind ) _GETOPT_THROW;
// harly.he add for reentrant 12.09/2013
extern _GETOPT_API void getopt_reset() _GETOPT_THROW;
_END_EXTERN_C
// Undefine so the macros are not included
# undef _BEGIN_EXTERN_C
# undef _END_EXTERN_C
# undef _GETOPT_THROW
# undef _GETOPT_API
# endif // __GETOPT_H_
getopt.cpp文件实现getopt函数:
# ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
# endif
# include <stdlib.h>
# include <stdio.h>
# include <tchar.h>
# include "getopt.h"
# ifdef __cplusplus
# define _GETOPT_THROW throw()
# else
# define _GETOPT_THROW
# endif
enum ENUM_ORDERING
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
};
struct _getopt_data
{
int optind;
int opterr;
int optopt;
TCHAR* optarg;
int __initialized;
TCHAR* __nextchar;
int __ordering;
int __posixly_correct;
int __first_nonopt;
int __last_nonopt;
};
static struct _getopt_data getopt_data = { 0, 0, 0, NULL, 0, NULL, 0, 0, 0, 0 };
TCHAR* optarg = NULL;
int optind = 1;
int opterr = 1;
int optopt = _T( '?' );
static void exchange( TCHAR** argv, struct _getopt_data* d )
{
int bottom = d->__first_nonopt;
int middle = d->__last_nonopt;
int top = d->optind;
TCHAR* tem;
while ( top > middle && middle > bottom )
{
if ( top - middle > middle - bottom )
{
int len = middle - bottom;
register int i;
for ( i = 0; i < len; i++ )
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - ( middle - bottom ) + i];
argv[top - ( middle - bottom ) + i] = tem;
}
top -= len;
}
else
{
int len = top - middle;
register int i;
for ( i = 0; i < len; i++ )
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
bottom += len;
}
}
d->__first_nonopt += ( d->optind - d->__last_nonopt );
d->__last_nonopt = d->optind;
}
static const TCHAR* _getopt_initialize( const TCHAR* optstring
, struct _getopt_data* d
, int posixly_correct )
{
d->__first_nonopt = d->__last_nonopt = d->optind;
d->__nextchar = NULL;
d->__posixly_correct = posixly_correct
| !!_tgetenv( _T( "POSIXLY_CORRECT" ) );
if ( optstring[0] == _T( '-' ) )
{
d->__ordering = RETURN_IN_ORDER;
++optstring;
}
else if ( optstring[0] == _T( '+' ) )
{
d->__ordering = REQUIRE_ORDER;
++optstring;
}
else if ( d->__posixly_correct )
{
d->__ordering = REQUIRE_ORDER;
}
else
{
d->__ordering = PERMUTE;
}
return optstring;
}
int _getopt_internal_r( int argc
, TCHAR *const * argv
, const TCHAR* optstring
, const struct option* longopts
, int* longind
, int long_only
, struct _getopt_data* d
, int posixly_correct )
{
int print_errors = d->opterr;
if ( argc < 1 )
{
return -1;
}
d->optarg = NULL;
if ( d->optind == 0 || !d->__initialized )
{
if ( d->optind == 0 )
{
d->optind = 1;
}
optstring = _getopt_initialize( optstring, d, posixly_correct );
d->__initialized = 1;
}
else if ( optstring[0] == _T( '-' ) || optstring[0] == _T( '+' ) )
{
optstring++;
}
if ( optstring[0] == _T( ':' ) )
{
print_errors = 0;
}
if ( d->__nextchar == NULL || *d->__nextchar == _T( '\0' ) )
{
if ( d->__last_nonopt > d->optind )
{
d->__last_nonopt = d->optind;
}
if ( d->__first_nonopt > d->optind )
{
d->__first_nonopt = d->optind;
}
if ( d->__ordering == PERMUTE )
{
if ( d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind )
{
exchange( ( TCHAR * * ) argv, d );
}
else if ( d->__last_nonopt != d->optind )
{
d->__first_nonopt = d->optind;
}
while ( d->optind
< argc
&& ( argv[d->optind][0] != _T( '-' )
|| argv[d->optind][1] == _T( '\0' ) ) )
{
d->optind++;
}
d->__last_nonopt = d->optind;
}
if ( d->optind != argc && !_tcscmp( argv[d->optind], _T( "--" ) ) )
{
d->optind++;
if ( d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind )
{
exchange( ( TCHAR * * ) argv, d );
}
else if ( d->__first_nonopt == d->__last_nonopt )
{
d->__first_nonopt = d->optind;
}
d->__last_nonopt = argc;
d->optind = argc;
}
if ( d->optind == argc )
{
if ( d->__first_nonopt != d->__last_nonopt )
{
d->optind = d->__first_nonopt;
}
return -1;
}
if ( ( argv[d->optind][0] != _T( '-' )
|| argv[d->optind][1] == _T( '\0' ) ) )
{
if ( d->__ordering == REQUIRE_ORDER )
{
return -1;
}
d->optarg = argv[d->optind++];
return 1;
}
d->__nextchar = ( argv[d->optind]
+ 1 + ( longopts != NULL
&& argv[d->optind][1] == _T( '-' ) ) );
}
if ( longopts != NULL
&& ( argv[d->optind][1] == _T( '-' )
|| ( long_only && ( argv[d->optind][2]
|| !_tcschr( optstring, argv[d->optind][1] ) )
)
)
)
{
TCHAR* nameend;
const struct option* p;
const struct option* pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = -1;
int option_index;
for ( nameend = d->__nextchar;
*nameend && *nameend != _T( '=' );
nameend++ )
;
for ( p = longopts, option_index = 0; p->name; p++, option_index++ )
{
if ( !_tcsncmp( p->name, d->__nextchar, nameend - d->__nextchar ) )
{
if ( ( unsigned int ) ( nameend - d->__nextchar )
== ( unsigned int ) _tcslen( p->name ) )
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if ( pfound == NULL )
{
pfound = p;
indfound = option_index;
}
else if ( long_only
|| pfound->has_arg != p->has_arg
|| pfound->flag != p->flag
|| pfound->val != p->val )
{
ambig = 1;
}
}
}
if ( ambig && !exact )
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: option '%s' is ambiguous\n" )
, argv[0]
, argv[d->optind] );
}
d->__nextchar += _tcslen( d->__nextchar );
d->optind++;
d->optopt = 0;
return _T( '?' );
}
if ( pfound != NULL )
{
option_index = indfound;
d->optind++;
if ( *nameend )
{
if ( pfound->has_arg )
{
d->optarg = nameend + 1;
}
else
{
if ( print_errors )
{
if ( argv[d->optind - 1][1] == _T( '-' ) )
{
_ftprintf( stderr
, _T( "%s: option '--%s' doesn't allow " )
_T( "an argument\n" )
, argv[0]
, pfound->name );
}
else
{
_ftprintf( stderr
, _T( "%s: option '%c%s' doesn't allow " )
_T( "an argument\n" )
, argv[0]
, argv[d->optind - 1][0]
, pfound->name );
}
}
d->__nextchar += _tcslen( d->__nextchar );
d->optopt = pfound->val;
return _T( '?' );
}
}
else if ( pfound->has_arg == 1 )
{
if ( d->optind < argc )
{
d->optarg = argv[d->optind++];
}
else
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: option '--%s' requires an " )
_T( "argument\n" )
, argv[0]
, pfound->name );
}
d->__nextchar += _tcslen( d->__nextchar );
d->optopt = pfound->val;
return optstring[0] == _T( ':' ) ? _T( ':' ) : _T( '?' );
}
}
d->__nextchar += _tcslen( d->__nextchar );
if ( longind != NULL )
{
*longind = option_index;
}
if ( pfound->flag )
{
*( pfound->flag ) = pfound->val;
return 0;
}
return pfound->val;
}
if ( !long_only
|| argv[d->optind][1]
== _T( '-' )
|| _tcschr( optstring
, *d->__nextchar )
== NULL )
{
if ( print_errors )
{
if ( argv[d->optind][1] == _T( '-' ) )
{
/* --option */
_ftprintf( stderr
, _T( "%s: unrecognized option '--%s'\n" )
, argv[0]
, d->__nextchar );
}
else
{
/* +option or -option */
_ftprintf( stderr
, _T( "%s: unrecognized option '%c%s'\n" )
, argv[0]
, argv[d->optind][0]
, d->__nextchar );
}
}
d->__nextchar = ( TCHAR * ) _T( "" );
d->optind++;
d->optopt = 0;
return _T( '?' );
}
}
{
TCHAR c = *d->__nextchar++;
TCHAR* temp = ( TCHAR* ) _tcschr( optstring, c );
if ( *d->__nextchar == _T( '\0' ) )
{
++d->optind;
}
if ( temp == NULL || c == _T( ':' ) || c == _T( ';' ) )
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: invalid option -- '%c'\n" )
, argv[0]
, c );
}
d->optopt = c;
return _T( '?' );
}
if ( temp[0] == _T( 'W' ) && temp[1] == _T( ';' ) )
{
TCHAR* nameend;
const struct option* p;
const struct option* pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = 0;
int option_index;
if ( *d->__nextchar != _T( '\0' ) )
{
d->optarg = d->__nextchar;
d->optind++;
}
else if ( d->optind == argc )
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: option requires an argument -- '%c'\n" )
, argv[0]
, c );
}
d->optopt = c;
if ( optstring[0] == _T( ':' ) )
{
c = _T( ':' );
}
else
{
c = _T( '?' );
}
return c;
}
else
{
d->optarg = argv[d->optind++];
}
for ( d->__nextchar = nameend = d->optarg;
*nameend && *nameend != _T( '=' );
nameend++ )
;
for ( p = longopts, option_index = 0;
p->name;
p++, option_index++ )
{
if ( !_tcsncmp( p->name
, d->__nextchar
, nameend - d->__nextchar ) )
{
if ( ( unsigned int ) ( nameend - d->__nextchar )
== _tcslen( p->name ) )
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if ( pfound == NULL )
{
pfound = p;
indfound = option_index;
}
else if ( long_only
|| pfound->has_arg != p->has_arg
|| pfound->flag != p->flag
|| pfound->val != p->val )
{
ambig = 1;
}
}
}
if ( ambig && !exact )
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: option '-W %s' is ambiguous\n" )
, argv[0]
, d->optarg );
}
d->__nextchar += _tcslen( d->__nextchar );
d->optind++;
return _T( '?' );
}
if ( pfound != NULL )
{
option_index = indfound;
if ( *nameend )
{
if ( pfound->has_arg )
{
d->optarg = nameend + 1;
}
else
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: option '-W %s' doesn't allow " )
_T( "an argument\n" )
, argv[0]
, pfound->name );
}
d->__nextchar += _tcslen( d->__nextchar );
return _T( '?' );
}
}
else if ( pfound->has_arg == 1 )
{
if ( d->optind < argc )
{
d->optarg = argv[d->optind++];
}
else
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: option '-W %s' requires an " )
_T( "argument\n" )
, argv[0]
, pfound->name );
}
d->__nextchar += _tcslen( d->__nextchar );
return optstring[0] == _T(':') ? _T(':') : _T('?');
}
}
else
{
d->optarg = NULL;
}
d->__nextchar += _tcslen( d->__nextchar );
if ( longind != NULL )
{
*longind = option_index;
}
if ( pfound->flag )
{
*( pfound->flag ) = pfound->val;
return 0;
}
return pfound->val;
}
d->__nextchar = NULL;
return _T( 'W' );
}
if ( temp[1] == _T( ':' ) )
{
if ( temp[2] == _T( ':' ) )
{
if ( *d->__nextchar != _T( '\0' ) )
{
d->optarg = d->__nextchar;
d->optind++;
}
else
{
d->optarg = NULL;
}
d->__nextchar = NULL;
}
else
{
if ( *d->__nextchar != _T( '\0' ) )
{
d->optarg = d->__nextchar;
d->optind++;
}
else if ( d->optind == argc )
{
if ( print_errors )
{
_ftprintf( stderr
, _T( "%s: option requires an " )
_T( "argument -- '%c'\n" )
, argv[0]
, c );
}
d->optopt = c;
if ( optstring[0] == _T( ':' ) )
{
c = _T( ':' );
}
else
{
c = _T( '?' );
}
}
else
{
d->optarg = argv[d->optind++];
}
d->__nextchar = NULL;
}
}
return c;
}
}
int _getopt_internal( int argc
, TCHAR *const * argv
, const TCHAR* optstring
, const struct option* longopts
, int* longind
, int long_only
, int posixly_correct )
{
int result;
getopt_data.optind = optind;
getopt_data.opterr = opterr;
result = _getopt_internal_r( argc
, argv
, optstring
, longopts
, longind
, long_only
, &getopt_data
, posixly_correct );
optind = getopt_data.optind;
optarg = getopt_data.optarg;
optopt = getopt_data.optopt;
return result;
}
int getopt( int argc, TCHAR *const * argv, const TCHAR* optstring) _GETOPT_THROW
{
return _getopt_internal( argc
, argv
, optstring
, ( const struct option * ) 0
, ( int * ) 0
, 0
, 0 );
}
int getopt_long( int argc
, TCHAR *const * argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index ) _GETOPT_THROW
{
return _getopt_internal( argc
, argv
, options
, long_options
, opt_index
, 0
, 0 );
}
int _getopt_long_r( int argc
, TCHAR *const * argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index
, struct _getopt_data* d )
{
return _getopt_internal_r( argc
, argv
, options
, long_options
, opt_index
, 0
, d
, 0 );
}
int getopt_long_only( int argc
, TCHAR *const * argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index ) _GETOPT_THROW
{
return _getopt_internal( argc
, argv
, options
, long_options
, opt_index
, 1
, 0 );
}
int _getopt_long_only_r( int argc
, TCHAR *const * argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index
, struct _getopt_data* d )
{
return _getopt_internal_r( argc
, argv
, options
, long_options
, opt_index
, 1
, d
, 0 );
}
void getopt_reset() _GETOPT_THROW
{
optarg = NULL;
optind = 1;
opterr = 1;
optopt = _T( '?' );
//
getopt_data.optind = 0;
getopt_data.opterr = 0;
getopt_data.optopt = 0;
getopt_data.optarg = NULL;
getopt_data.__initialized = 0;
getopt_data.__nextchar = NULL;
getopt_data.__ordering = 0;
getopt_data.__posixly_correct = 0;
getopt_data.__first_nonopt = 0;
getopt_data.__last_nonopt = 0;
}
4. 编译
在根目录下执行以下指令:
# 构建build目录
mkdir build
# 开始构建
cmake -S . -B ./build -G "MinGW Makefiles"
cd build
# 编译
nmake
完成编译后的目录如下所示(关注build目录下生成内容):