首页 > 系统相关 >Linux基础知识(11)- GCC 简单使用(一)| GCC 安装配置和 Makefile 的基本用法

Linux基础知识(11)- GCC 简单使用(一)| GCC 安装配置和 Makefile 的基本用法

时间:2022-12-09 13:33:18浏览次数:45  
标签:11 gcc target make GCC Linux main hello


GCC 的全拼为 GNU C Compiler,即 GUN 计划诞生的 C 语言编译器,显然最初 GCC 的定位确实只用于编译 C 语言。但经过这些年不断的迭代,GCC 的功能得到了很大的扩展,它不仅可以用来编译 C 语言程序,还可以处理 C++、Go、Objective -C 等多种编译语言编写的程序。与此同时,由于之前的 GNU C Compiler 已经无法完美诠释 GCC 的含义,所以其英文全称被重新定义为  GNU Compiler Collection,即 GNU 编译器套件。

所谓编译器,可以简单地将其理解为 “翻译器”。要知道,计算机只认识二进制指令(仅有 0 和 1 组成的指令),我们日常编写的 C 语言代码、C++ 代码、Go 代码等,计算机根本无法识别,只有将程序中的每条语句翻译成对应的二进制指令,计算机才能执行。

GCC 编译器从而停止过改进。截止 2020 年 5 月,GCC 已经从最初的 1.0 版本发展到了 10.1 版本,期间历经了上百个版本的迭代。作为一款最受欢迎的编译器,GCC 被移植到数以千计的硬件/软件平台上,几乎所有的 Linux 发行版也都默认安装有 GCC 编译器。GCC 支持的硬件平台(部分):

 

硬件 操作系统
Alpha Red Hat Linux
HPPA HPUX
Intel x86 Debian Linux、Red Hat Linux 和 FreeBSD
MIPS IRIX
PowerPC AIX
Sparc Solaris

 

1. GCC 安装配置

    Linux 操作系统的自由、开源,在其基础上衍生出了很多不同的 Linux 操作系统,如 CentOS、Ubuntu、Debian 等。这些 Linux 发行版中,大多数都默认装有 GCC 编译器(版本通常都较低)。

    1) CentOS 7.9 下安装

        查看当前 GCC 版本:

            $ gcc --version

                -bash: gcc: command not found

                注:表明当前系统没有安装 GCC 编译器。

        (1) 基于 yum 安装

            $ sudo yum -y install gcc gcc-c++

                ...

                Installed:
                  gcc.x86_64 0:4.8.5-44.el7                                gcc-c++.x86_64 0:4.8.5-44.el7

                Dependency Installed:
                  cpp.x86_64 0:4.8.5-44.el7                               glibc-devel.x86_64 0:2.17-326.el7_9
                  glibc-headers.x86_64 0:2.17-326.el7_9                   kernel-headers.x86_64 0:3.10.0-1160.80.1.el7
                  libmpc.x86_64 0:1.0.1-3.el7                             libstdc++-devel.x86_64 0:4.8.5-44.el7
                  mpfr.x86_64 0:3.1.1-4.el7

                Complete!


            $ gcc --version

                gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
                Copyright (C) 2015 Free Software Foundation, Inc.
                This is free software; see the source for copying conditions.  There is NO
                warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 


            注:基于 yum 默认安装的 GCC 版本由 CentOS 的版本决定,由于 CentOS 7.9 下默认安装的 GCC 4.8.5 版本太低(低版本 GCC 默认的 C89 的标准不支持某些 C 语法,需要编译时指定 -std=语法标准),所以我们这里再手动安装更高版本的 GCC 。
     
        (2) 手动安装

            下载高版本源码安装包,安装前需要 CentOS 7.9 上已经安装低版本的 GCC,因为以源码的方式安装 GCC 编译器,即手动编译 GCC 编译器的源码,需要当前系统中存在一个可用的编译器。

            GCC 下载地址:https://mirrors.aliyun.com/gnu/gcc/,这里下载 gcc-9.4.0.tar.gz 并复制到 ~/ 目录,具体安装过程如下:

                $ cd ~/

                # 解压至 /usr/local 目录下
                $ sudo tar -vzxf gcc-9.4.0.tar.gz -C /usr/local     
                $ cd /usr/local/gcc-9.4.0

                # 下载安装 GCC 所需要的依赖包(如 gmp、mpfr、mpc 等),
                # 要确保这些依赖包被成功下载后,才能继续执行下面的安装步骤
                $ sudo ./contrib/download_prerequisites

                    ...

                    gmp-6.1.0.tar.bz2: OK
                    mpfr-3.1.4.tar.bz2: OK
                    mpc-1.0.3.tar.gz: OK
                    isl-0.18.tar.bz2: OK
                    All prerequisites downloaded successfully.


                # 手动创建一个目录,用于存放编译 GCC 源码包生成的文件
                $ sudo mkdir build-9.4.0
                $ cd build-9.4.0

                # GCC 编译器支持多种编程语言的编译,配置 GCC 支持编译 C 和 C++ 语言 (其它语言:java、objc、obj-c++、go 等)
                $ sudo ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib

                # 使用 make 命令来编译和安装
                $ sudo make & make install

                $ gcc --version

                    gcc (GCC) 9.4.0
                    Copyright (C) 2019 Free Software Foundation, Inc.
                    This is free software; see the source for copying conditions.  There is NO
                    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    2) Ubuntu 20.04 下安装

        查看当前 GCC 版本:

            $ gcc --version

                Command 'gcc' not found, but can be installed with:

                sudo apt install gcc

                注:表明当前系统没有安装 GCC 编译器。

        基于 apt-get 安装:

            $ sudo apt install gcc g++ make

                ...

                Setting up gcc-9 (9.4.0-1ubuntu1~20.04.1) ...
                Setting up gcc (4:9.3.0-1ubuntu2) ...
                Setting up g++-9 (9.4.0-1ubuntu1~20.04.1) ...
                Setting up g++ (4:9.3.0-1ubuntu2) ...
                Setting up make (4.2.1-1.2) ...
                update-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode
                Processing triggers for man-db (2.9.1-1) ...
                Processing triggers for libc-bin (2.31-0ubuntu9.9) ...


            $ gcc -version

                gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
                Copyright (C) 2019 Free Software Foundation, Inc.
                This is free software; see the source for copying conditions.  There is NO
                warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

            注:Ubuntu 20.04 版本默认安装了 GCC 9.4.0,这里不需要手动安装更高版本的 GCC。


2. Hello World

    使用 vim 编辑器,编写 C 和 C++ 程序,其功能是输出 "Hello World!"。如果 vim 编辑器没有安装,可以运行如下命令安装 vim:      

        $ sudo apt-get install vim     # CentOS 下运行 sudo yum -y install vim

    1) C 程序

        $ cd ~/
        $ vim hello.c

            #include <stdio.h>
            
            int main() {
                puts("Hello World!- C");
                return 0;
            }


        # gcc 编译
        $ gcc hello.c -o hello

        $ ./hello

            Hello World! - C

    2) C++ 程序

        $ vim hello2.cpp

            #include <iostream>
            using namespace std;
            
            int main() {
                cout << "Hello World! - C++" << endl;
                return 0;
            }


        # g++ 编译
        $ g++ hello2.cpp -o hello2

        $ ./hello2

            Hello World! - C++

     3) GCC/G++ 常用的指令选项

指令选项 描述
-E(大写) 预处理指定的源文件,不进行编译。
-S(大写) 编译指定的源文件,但是不进行汇编。
-c 编译、汇编指定的源文件,但是不进行链接。
-o 指定生成文件的文件名。
-llibrary(-I library)    其中 library 表示要搜索的库文件的名称。该选项用于手动指定链接环节中程序可以调用的库文件。建议 -l 和库文件名之间不使用空格,比如 -lstdc++。
-ansi 对于 C 语言程序来说,其等价于 -std=c90;对于 C++ 程序来说,其等价于 -std=c++98。
-std= 手动指令编程语言所遵循的标准,例如 c89、c90、c++98、c++11 等。

        注:以上仅列出的一些常用指令选项,GCC 编译器提供有大量的指令选项,更多的指令选项,可以查看 GCC 手册 -> https://gcc.gnu.org/onlinedocs/gcc-10.1.0/gcc/Invoking-GCC.html#Invoking-GCC。


3. Makefile 的基本用法

    上文我们使用 “gcc hello.c -o hello” 命令把 hello.c 源文件编译成了 hello 可执行程序(类似 Windows 下的 *.exe 文件)。

    编译一个 *.c 文件(这里没有用到 *.h 头文件),可以用单命令行的方式很简单的实现,如果项目中有很多个 *.c 文件和 *.h 头文件,用单命令行方式编译,视乎是一件不可思议的事情。

    要解决这个问题,最好的方式就是把项目的编译规则写下来,让编译器自动加载该规则进行编译,也就是使用 make 命令和 Makefile 文件。关于 make 命令和 Makefile 文件,具体描述如下:

        make 命令:它可以帮助我们找出项目里面修改变更过的文件,并根据依赖关系,找出受修改影响的其他相关文件,然后对这些文件按照规则进行单独的编译,避免重新编译项目的所有的文件;

        Makefile 文件:上面提到的规则、依赖关系就定义在这个 Makefile 文件中,定义文件的依赖关系之后,make 命令就能精准地进行编译工作;

        注:GNU 官方的 make 说明文档:https://www.gnu.org/software/make/manual

    1) Makefile 示例

        创建 Makefile 文件,内容如下:

            # target_a 是第一个目标,是最终目标,即 make 的默认目标
            # 执行 ls 命令列出当前目录下的内容,target_a 依赖于 target_b 和 target_c
            target_a: target_b target_c
                ls

            # 执行 touch 命令创建 test.txt 文件,target_b 无依赖
            target_b:
                touch test.txt

            # 执行 pwd 命令显示当前路径,target_c 无依赖
            target_c:
                pwd

            # 执行 rm 命令删除 test.txt 文件,target_d 无依赖
            target_d:
                rm -f test.txt


            注:命令行之前是 tab 键,不能是空格。vim 的默认 tab 是 8 个空格,建议创建或修改 vim 的配置文件 ~/.vimrc,添加:

                set tabstop=4   // 设置 tab 键是 4 个空格
                set noexpandtab  // 不把 tab 键用空格代替

        运行:

            $ ls

                hello  hello2  hello2.cpp  hello.c  Makefile

            $ make

                touch test.txt
                pwd
                /home/xxx
                ls
                hello  hello2  hello2.cpp  hello.c  Makefile  test.txt

            $ make target_d

                rm -f test.txt

            $ make target_b

                touch test.txt

            $ make target_c

                pwd
                /home/xxx


            注:target_d 不是默认目标,且不被其它任何目标依赖,所以直接 make 时 target_d并没有被执行,可以使用 “make 目标名” 的语法执行指定的目标。

                make 命令和 Makefile 文件一起配合使用,从原理上讲有点类似于 Windows 的批处理程序 (*.bat)。


    2) 使用 Makefile 编译程序

        (1) 创建多个文件

            创建 hello_main.c 文件,内容如下:

                #include "hello_func.h"

                int main() {
                    hello_func();
                    return 0;
                }


            创建 hello_func.c 文件,内容如下:

                #include <stdio.h>
                #include "hello_func.h"

                void hello_func(void) {

                    printf("Hello world - Makefile!\n");
                    for (int i=0; i<3; i++ ) {
                        printf("output i=%d\n",i);
                    }
                }


            创建 hello_func.h 文件,内容如下:

                void hello_func(void);

        (2) 命令行编译

            # 注意最后的 "-I ." 包含名点 "."
            $ gcc -o hello_main hello_main.c hello_func.c -I .

            # 运行生成的 hello_main 程序
            $ ./hello_main

                Hello world - Makefile!
                output i=0
                output i=1
                output i=2

            注:低版本的 gcc 默认使用的 C89 的标准不支持 for 中定义循环变量,需要增加 -std=c99 或 -std=gun99 参数才能编译通过。比如:

                gcc -o hello_main hello_main.c hello_func.c -std=gnu99 -I .

        (3) Makefile 编译

            创建 Makefile 文件,内容如下:

                # 默认目标,hello_main 依赖于 hello_main.c 和 hello_func.c
                hello_main: hello_main.c hello_func.c
                    gcc -o hello_main hello_main.c hello_func.c -I .

                # clean目标,删除编译生成的中间文件
                clean:
                    rm -f *.o hello_main


            运行:

                $ make

                    gcc -o hello_main hello_main.c hello_func.c -I .

                $ ./hello_main

                    Hello world - Makefile!
                    output i=0
                    output i=1
                    output i=2

                # 再次 make,会提示 hello_main 文件已是最新
                $ make

                    make: `hello_main' is up to date.

                # 使用 touch 命令更新一下 hello_func.c 的时间
                $ touch hello_func.c

                # 再次 make,由于 hello_func.c 比 hello_main 新,所以会再编译
                $ make

                    gcc -o hello_main hello_main.c hello_func.c -I .


    3) Makefile 语法

        语法格式:

            [目标1]:[依赖]
            [命令1]
            [命令2]

            [目标2]:[依赖]
            [命令1]
            [命令2]

        说明:

            (1) 目标:指 make 要做的事情,可以是一个简单的代号,也可以是目标文件,需要顶格书写,前面不能有空格或 Tab。一个 Makefile 可以有多个目标,写在最前面的第一个目标,会被 Make 程序确立为 “默认目标”,例如前面的 target_a、hello_main;

            (2) 依赖:要达成目标需要依赖的某些文件或其它目标。例如前面的 target_a 依赖于 target_b 和target_c,又如在编译的例子中,hello_main 依赖于 hello_main.c、hello_func.c 源文件,若这些文件更新了会重新进行编译;

            (3) 命令1、命令2 … 命令n:make 达成目标所需要的命令。只有当目标不存在或依赖文件的修改时间比目标文件还要新时,才会执行命令。要特别注意命令的开头要用 “Tab” 键,不能使用空格代替,有的编辑器会把 Tab 键自动转换成空格导致出错,若出现这种情况请检查自己的编辑器配置。


标签:11,gcc,target,make,GCC,Linux,main,hello
From: https://www.cnblogs.com/tkuang/p/16968689.html

相关文章

  • Linux-jar操作脚本
    service.sh使用说明:./service.shstart./service.shstop#!/bin/bash#这里可替换为你自己的执行程序,其他代码无需更改APP_NAME=mxy_system-0.0.1-SNAPSHOT.jar#she......
  • widow linux 查看端口被占用的进程ID
    有时候进程觉得关闭了但是并没有真正的关闭重启应用的时候会出现端口号冲突这个时候就需要手动去查询端口号占用情况。linux查看端口占用8080表示需要查询的端口号......
  • python中os.system(cmd)函数的返回值:python中的os.system(cmd)的返回值与linux命令返
    前言①在实际开发过程中,经常会遇到在Python代码中调用shell脚本,再获取脚本返回的返回值的情况: os.system(cmd) ②由于系统环境的问题, os.system(cmd) 函数执行命令后......
  • Linux文件系统
    ext2作为索引式文件系统,一个文件占用一个inode,记录着文件的权限和属性,同时记录此文件的数据所在的block号码;磁盘分区的好处:以mysql是数据目录为例,如果将数据目录单独放在......
  • [置顶]【Linux init】systemd 服务单元管理
    控制systemd系统和服务管理,并行启动服务时充分发挥了多核处理器的性能,缩短了系统启动所需时间。先前的使用SysV初始化或Upstart的红帽企业版Linux版本中,使用位于/etc/rc.......
  • linux 系统状态分析
    cat/proc/sys/kernel/ostype cat/proc/versionshell:www.jb51.net/article/51574.htmpresident.blog.51cto.com/4990508/854647/president.blog.51cto.com/4990508/8542......
  • linux c ipc机制
    ipcipc意思就是进程间通信机制的简称在linux(centos)环境下使用ipcs(信息查看),ipcrm(删除),ipcmk(创建)通过指令ipcs查看,linux支持的IPC机制有三种Message......
  • Linux系统常见的三种设备分类!
    Linux系统中设备主要分为哪几类?在Linux中,设备主要分为三种,分别是:块设备、字符设备和网络设备,接下来通过这篇文章详细介绍一下。Linux系统中的设备可以分为字符设备......
  • itop3588开发板编译Linux源码包-修改成mipi显示
    打开​​Linux​​源码kernel/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi中的设备树文件。如下图所示默认包含的头文件即是mipi显示:更多内容可以了解迅为35......
  • itop3568开发板在Linux系统中使用NPU
    下载rknpu2并拷贝虚拟机​​Ubuntu​​,如下图所示,RKNPU2提供了访问rk3568芯片NPU的高级接口。下载地址为“iTOP-3568开发板\02_【iTOP-RK3568开发板】开发资料\11_NPU使......