ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

手写g++编译命令行工具笔记

2022-06-23 23:38:20  阅读:133  来源: 互联网

标签:std return ++ cmd 编译 str 返回值 手写


基本想法

为什么要写 CPPRUN:

  1. 如果要开警告开关,敲完整的编译代码还挺麻烦的
  2. 想要编译与运行一次性完成
  3. Windows 的控制台本来是 cmd,后来有了 Powershell,但是后者不能用 < 指定输入文件,比较麻烦

所以可以直接用 C++ 写一个类似于脚本的命令行程序。

功能

  1. 编译单个源代码。
  2. 默认情况下若编译成功,则运行程序,可以指定输入输出文件。
  3. 毫秒级计算实际运行时间。

基本用法:
.\run <源程序文件名,不包括.cpp扩展> <其他指令>
指令列表:

  • \i <文件名> 指定输入文件
  • \o <文件名> 指定输出文件
  • \f <文件名,不带扩展名> 指定exe文件名,默认与源文件相同
  • \std <c++/c++11/c++14> 设置C++版本,默认 C++14
  • \u 取消警告,默认开启 -Wall -Wextra -Wconversion -Wshadow
  • \cmd 回显编译命令,默认不开启
  • \comp 只编译不运行,默认编译后立即运行

代码实现

命令行程序添加参数

以 CPPRUN 为例,.\run <...> 中的 <...> 就是参数。在 C++ 中 main 函数其实是有两个参数的(只是竞赛的时候从来不会用到,也可以不写),即

// 参数随便命名,这里举个例子
int main(int argc, char** argv) {
}

其中 argc 是 ”参数数量“ + 1,注意命令行中不同参数用若干空格隔开;argv[1 ~ argc - 1] 是字符串形式的参数。

在程序中形成编译命令并执行

C风格字符串的拼接还挺麻烦,可以直接用 iostream 中的 string,通过 +, += 可以完成字符串与字符、字符串与字符串的拼接。

执行需要用到 system 函数,但是 system 的参数是C风格字符串,string 类型需要用到内置的 c_str() 转化。另外一提,在 system 中是可以使用 <, > 指定输入输出文件的,因为其本质是在 cmd 中执行了指令。相当于免去了在 Powershell 中打开 cmd 执行指令再关闭 cmd 的这种繁琐的操作。

system 函数是有返回值的,就是执行的该条指令的返回值。这样可以获取程序的返回值判断程序是否正常结束,也可以通过 g++ 的返回值判断是否有编译错误。

Tab. g++ 返回 0 是编译成功(包括有编译警告),其余返回值是有编译错误。

其他的小细节

如果想要在命令行中输出中文,一定保证你的源文件是在 GBK(或者其他中文) 的编码下编写并保存的!

源代码

/* Lucky_Glass */
// 2022-6-21 modified
#include <windows.h>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <iostream>

int getOption(char *_str) {
  std::string str(_str);
  if (str == "\\i") return 1;
  if (str == "\\o") return 2;
  if (str == "\\f") return 3;
  if (str == "\\std") return 4;
  if (str == "\\u") return 5;
  if (str == "\\cmd") return 6;
  if (str == "\\comp") return 7;
  return 0;
}
void somethingError() {
  std::cerr << "<fail> CPPRUN发生了未知错误" << std::endl;
  exit(1);
}

bool isopt[50];
int main(int num, char *opt[]) {
  std::string cmd("g++ ");
  if (num == 1) {
    std::cerr << "<fail> 请指定编译文件" << std::endl;
    return 0;
  }
  std::string fil(opt[1]), inp, oup, gver("c++14");
  cmd += fil, cmd += ".cpp";
  for (int i = 2; i < num; ++i) {
    int optid = getOption(opt[i]);
    isopt[optid] = true;
    if (optid <= 4) {
      std::string ext(opt[++i]);
      switch (optid) {
        case 1: inp = ext; break;
        case 2: oup = ext; break;
        case 3: fil = ext; break;
        case 4: gver = ext; break;
        default: somethingError();
      }
    }
  }

  cmd += " -o ", cmd += fil;
  if (gver == "c++14") cmd += " -std=c++14";
  else if (gver == "c++11") cmd += " -std=c++11";
  else if (gver != "c++") {
    std::cerr << "<fail> C++版本只能为 c++/c++11/c++14" << std::cerr;
    return 0;
  }

  if (!isopt[5])
    cmd += " -Wall -Wextra -Wconversion -Wshadow";
  
  if (isopt[6])
    std::cerr << cmd << std::endl;

  if(!system(cmd.c_str()))
    std::cerr << "<success> 编译完成" << std::endl;
  else
    std::cerr << "<fail> 编译失败"  << std::endl;

  if (!isopt[7]) {
    cmd = ".\\", cmd += fil, cmd += ".exe";
    if (isopt[1]) cmd += " < ", cmd += inp;
    if (isopt[2]) cmd += " > ", cmd += oup;
    DWORD stt, edt;
    stt = GetTickCount();
    int ret = system(cmd.c_str());
    edt = GetTickCount();
    std::cerr.precision(3);
    std::cerr << "<success> 运行结束,返回值 " << ret
              << ",运行时间 " << (edt - stt) / 1000.0
              << std::endl;
  }
  return 0;
}

THE END

标签:std,return,++,cmd,编译,str,返回值,手写
来源: https://www.cnblogs.com/LuckyGlass-blog/p/16407180.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有