1.怎么用gcc编译文件?
2.UMI3源码解析系列之构建原理
3.什么是源码GCC编译器?
怎么用gcc编译文件?
在终端中输入 gcc 文件名 -o 目标文件名
然后 ./目标文件名 就行了,没有目标文件名,源码自动存为 a
执行 ./a 就行了。源码
在使用Gcc编译器的源码时候,我们必须给出一系列必要的源码调用参数和文件名称。GCC编译器的源码毕设源码分享调用参数大约有多个,其中多数参数我们可能根本就用不到,源码这里只介绍其中最基本、源码最常用的源码参数。
GCC最基本的源码用法是∶gcc [options] [filenames]
其中options就是编译器所需要的参数,filenames给出相关的源码文件名称。
-c,源码只编译,源码不连接成为可执行文件,源码编译器只是源码由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename,外卖跑腿源码JAVA确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。
-O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是明天跑指标源码,编译、连接的速度就相应地要慢一些。
-O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
-Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。C程序中的头文件包含两种情况∶
A)#include <myinc.h>
B)#include “myinc.h”
其中,A类使用尖括号(< >),B类使用双引号(“ ”)。对于A类,预处理程序cpp在系统预设包含文件目录(如/usr/include)中搜寻相应的文件,而B类,谷底线公式源码预处理程序在目标文件的文件夹内搜索相应文件。
GCC执行过程示例
示例代码 a.c:
#include <stdio.h>
int main()
{
printf("hello\n");
}
预编译过程:
这个过程处理宏定义和include,并做语法检查。
可以看到预编译后,代码从5行扩展到了行。
gcc -E a.c -o a.i
cat a.c | wc -l
5
cat a.i | wc -l
编译过程:
这个阶段,生成汇编代码。
gcc -S a.i -o a.s
cat a.s | wc -l
汇编过程:
这个阶段,生成目标代码。
此过程生成ELF格式的目标代码。
gcc -c a.s -o a.o
file a.o
a.o: ELF -bit LSB relocatable, AMD x-, version 1 (SYSV), not stripped
链接过程:
链接过程。生成可执行代码。链接分为两种,一种是静态链接,另外一种是动态链接。使用静态链接的仿图怪兽源码好处是,依赖的动态链接库较少,对动态链接库的版本不会很敏感,具有较好的兼容性;缺点是生成的程序比较大。使用动态链接的好处是,生成的程序比较小,占用较少的内存。
gcc a.o -o a
程序运行:
./a
hello
编辑本段
GCC编译简单例子
编写如下代码:
#include <stdio.h>
int main()
{
printf("hello,world!\n");
}
执行情况如下:
gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o
gcc hello.c -o hello
./hello
hello,world!
UMI3源码解析系列之构建原理
基于前面umi插件机制的原理可以了解到,umi是一个插件化的企业级前端框架,它配备了完善的插件体系,这也使得umi具有很好的可扩展性。umi的全部功能都是由插件完成的,构建功能同样是以插件的形式完成的。下面将从以下两个方面来了解umi的构建原理。UMI命令注册想了解umi命令的注册流程,咱们就从umi生成的项目入手。
从umi初始化的项目package.json文件看,umi执行dev命令,实际执行的是start:dev,而start:dev最终执行的是umidev。
"scripts":{ "dev":"npmrunstart:dev","start:dev":"cross-envREACT_APP_ENV=devMOCK=noneUMI_ENV=devumidev"}根据这里的umi命令,我们找到node_modules里的umi文件夹,看下umi文件夹下的package.json文件:
"name":"umi","bin":{ "umi":"bin/umi.js"}可以看到,这里就是定义umi命令的地方,而umi命令执行的脚本就在bin/umi.js里。接下来咱们看看bin/umi.js都做了什么。
#!/usr/bin/envnoderequire('v8-compile-cache');constresolveCwd=require('@umijs/deps/compiled/resolve-cwd');const{ name,bin}=require('../package.json');constlocalCLI=resolveCwd.silent(`${ name}/${ bin['umi']}`);if(!process.env.USE_GLOBAL_UMI&&localCLI&&localCLI!==__filename){ constdebug=require('@umijs/utils').createDebug('umi:cli');debug('Usinglocalinstallofumi');require(localCLI);}else{ require('../lib/cli');}判断当前是否执行的是本地脚手架,若是,则引入本地脚手架文件,否则引入lib/cli。在这里,我们未开启本地脚手架指令,所以是引用的lib/cli。
//获取进程的版本号constv=process.version;//通过yParser工具对命令行参数进行处理,此处是将version和help进行了简写constargs=yParser(process.argv.slice(2),{ alias:{ version:['v'],help:['h'],},boolean:['version'],});//若参数中有version值,并且args._[0]为空,此时将version字段赋值给args._[0]if(args.version&&!args._[0]){ args._[0]='version';constlocal=existsSync(join(__dirname,'../.local'))?chalk.cyan('@local'):'';console.log(`umi@${ require('../package.json').version}${ local}`);//若参数中无version值,并且args._[0]为空,此时将help字段复制给args._[0]}elseif(!args._[0]){ args._[0]='help';}处理完version和help后,紧接着会执行一段自执行代码:
(async()=>{ try{ //读取args._中第一个参数值switch(args._[0]){ case'dev'://若当前运行环境是dev,则调用Node.js的核心模块child_process的fork方法衍生一个新的Node.js进程。scriptPath表示要在子进程中运行的模块,这里引用的是forkedDev.ts文件。constchild=fork({ scriptPath:require.resolve('./forkedDev'),});//ref:///api/process/signal_events.html///post/什么是GCC编译器?
Linux系统下的GCC(GNU Compiler Collection)是GNU项目推出的功能强大、性能卓越的多平台编译器套装,其中GCC的核心组件是GNU C Compiler,它是GNU项目的代表作之一。GCC能够在多种硬件平台上编译出可执行程序,其平均编译效率比一般编译器高出%至%。GCC编译器能够将C、C++语言的源代码、汇编语言源代码和目标代码编译、连接成可执行文件;如果没有指定可执行文件名,GCC将默认生成名为a.out的文件。在Linux系统中,可执行文件没有统一的后缀,系统通过文件属性来区分可执行文件和普通文件。而GCC通过文件后缀来区分输入文件的类型,以下是一些常见的文件后缀及其含义:
- .c 后缀的文件是C语言源代码文件;
- .a 后缀的文件是由目标文件组成的库文件;
- .C、.cc 或 .cxx 后缀的文件是C++源代码文件;
- .h 后缀的文件是程序包含的头文件;
- .i 后缀的文件是预处理过的C源代码文件;
- .ii 后缀的文件是预处理过的C++源代码文件;
- .m 后缀的文件是Objective-C源代码文件;
- .o 后缀的文件是编译后的目标文件;
- .s 后缀的文件是汇编语言源代码文件;
- .S 后缀的文件是预编译的汇编语言源代码文件。
GCC的执行过程包括预处理、编译、汇编和连接四个步骤。虽然我们通常称GCC是C语言的编译器,但它的功能远不止编译C语言,使用GCC从C语言源代码生成可执行文件的过程实际上是这四个步骤的组合。
GCC的基本用法是:gcc [options] [filenames],其中options是编译器需要的参数,filenames是相关的文件名称。
常见的GCC选项包括:
- -c,仅编译,不进行连接,用于编译不包含主程序的子程序文件;
- -o output_filename,指定输出文件名,避免与源文件同名;
- -g,生成供GNU gdb使用的调试信息;
- -O,进行程序优化编译和连接;
- -O2,进行更高级的程序优化编译和连接;
- -Idirname,将dirname指定的目录添加到头文件搜索路径中;
- -Ldirname,将dirname指定的目录添加到库文件搜索路径中;
- -lname,在连接时加载名为“libname.a”的库文件。
在使用GCC时,如果出现错误,通常分为四类:
1. C语法错误:源代码文件中的语法错误,需要检查并修正代码;
2. 头文件错误:找不到头文件,可能是因为头文件名错误或所在目录名错误;
3. 库文件错误:连接程序找不到所需的库文件,需要检查并修正库文件名或目录名;
4. 未定义符号错误:在连接过程中出现,可能是因为未定义的函数或全局变量,或者未指定所需的库文件。
解决GCC编译、连接过程中的错误是程序设计的一个基本步骤,但仅仅是开始。程序在运行过程中可能出现的问题需要更深入的测试、调试和修改。