`
lveyo
  • 浏览: 915419 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

linux下GCC编译C程序(一)

阅读更多
GNU编译器集
    GNU编译器集(其前身为GNU C编译器)诞生于1987年。当时Richard Stallman(GNU项目的创办人)想要创建一个编译器,它可以满足他定义的“自由软件”概念,并可用来编译GNU项目发布的其他软件。GNU C编译器迅速在自由软件社区中流行开来,而且以其健壮性和可移植性而闻名。它已成为许多集成开发工具的基础,被世界各地的发行商应用在Linux和其他操作系统之上。
    GCC已不再是主要针对GNU项目自身的软件的小型C语言编译器了。如今,它已支持了许多不同的语言,包括C、C++、Ada、Fortran、Objective C,甚至还有Java。事实上,现代Linux系统除了可以自豪地炫耀那些由GNU工具直接支持的语言以外,它还支持大量其他语言。日益流行的脚本语言Perl、Python和Ruby,以及正在不断发展的mono 可移植C#实现的确有助于冲淡人们对Linux编程的传统看法,但这完全是另外一个问题了。

Linux内核和许多其他自由软件以及开放源码应用程序都是用C语言编写并使用GCC编译的。

1. 编译单个源文件

为了进行测试,你可以创建“Hello World”程序:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
        printf("Hello world!\n");
        exit(0);
}



使用如下命令编译并测试这个代码:
引用
# gcc -o hello hello.c
# ./hello
Hello wordl!


在默认情况下产生的可执行程序名为a.out,但你通常可以通过gcc的“-o”选项来指定自己的可执行程序名称。

2. 编译多个源文件

源文件message.c包含一个简单的消息打印函数:
#include <stdio.h>

void goodbye_world(void)
{
        printf("Goodbye, world!\n");
}


使用gcc的“-c”标记来编译支持库代码:
引用
# gcc -c message.c


这一过程的输出结果是一个名为message.o的文件,它包含适合连接到一个较大程序的已编译目标代码。

创建一个简单的示例程序,它包含一个调用goodbye_world的main函数

#include <stdlib.h>

void goodbye_world(void):

int main(int argc, char **argv)
{
        goodbye_world();
        exit(0);
}


使用GCC编译这个程序:
引用
# gcc -c main.c


现在有了两个目标文件:message.o和main.o。它们包含能够被Linux执行的目标代码。要从这个目标代码创建Linux可执行程序,需要再一次调用GCC来执行连接阶段的工作:
引用
# gcc -o goodbye message.o main.o


运行编译结果:
引用
# ./goodbye
Goodbye, world!


前面这些单独的步骤也可以简化为一个命令,这是因为GCC对如何将多个源文件编译为一个可执行程序有内置的规则。
引用
# gcc -o goodbye message.c main.c
# ./goodbye
Goodbye, world!


3. 使用外部函数库
GCC常常与包含标准例程的外部软件库结合使用,几乎每一个Linux应用程序都依赖于由GNU C函数库GLIBC。
应用外部函数库的例子:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX_INPUT 25

int main(int agrc, char **argv)
{
        char input[MAX_INPUT];
        double angle;

        printf("Give me an angle (in radians) ==>");
        if(!fgets(input, MAX_INPUT, stdin)){
                perror("an error occurred.\n");
        }
        angle = strtod(input, NULL);

        printf("sin(%e) = %e\n", angle, sin(angle));

        return 0;
}
编译命令:
引用
# gcc -o trig -lm trig.c


GCC的"-lm"选项,它告诉GCC查看系统提供的数学库(libm)。因为Linux和UNIX的系统函数库通常以"lib"为前缀,所以我们假设它存在。真正的函数库位置随系统的不同而不同,但它一般会位于目录/lib或/usr/lib中,在这些目录中还有数以百计的其他必需的系统函数库。

4. 共享函数库与静态函数库

Linux系统上的函数库分为两种不同的类型:共享的和静态的

静态函数库:每次当应用程序和静态连接的函数库一起编译时,任何引用的库函数中的代码都会被直接包含进最终的二进制程序。

共享函数库:包含每个库函数的单一全局版本,它在所有应用程序之间共享。这一过程背后所涉及的机制相当复杂,但主要依靠的是现代计算机的虚拟内存能力,它允许包含库函数的物理内存安全地在多个独立用户程序之间共享。

使用共享函数库不仅减少了文件的容量和Linux应用程序在内存中覆盖的区域,而且它还提高了系统的安全性。一个被许多不同程序同时调用的共享函数库很可能会驻留在内存中,以在需要使用它时被立即使用,而不是位于磁盘的交换分区中。这有助于进一步减少一些大型Linux应用程序的装载时间。

将上面的message.c作为共享库函数使用的例子:

引用
# gcc -fPIC -c message.c

“PIC”命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译输出的文件message.o可以被用于建立共享函数库,我们只需使用gcc的“-shared”标记即可:
引用
# gcc -shared -o libmessage.so message.o


将上面的mian.c使用共享库函数ligmessage.so编译:
引用
# gcc -o goodbye -lmessage -L. message.o
“-lmessage”标记来告诉GCC在连接阶段引用共享函数库libmessage.so。“-L.”标记告诉GCC函数库可能位于当前目录中,否则GNU的连接器会查找标准系统函数库目录,在本例的情况下,就找不到可用的函数库了。

此时运行编译好的goodbye会提示找不到共享函数库:
引用
#./goodbye
./goodbye: error while loading shared libraries: libmessage.so: cannot open shared object file: No such file or directory


可以使用命令ldd来发现一个特定应用程序需要使用的函数库。ldd搜索标准系统函数库路径并显示一个特定程序使用的函数库版本。
引用
#ldd goodbye
        linux-gate.so.1 =>  (0x00493000)
        libmessage.so => not found
        libc.so.6 => /lib/libc.so.6 (0x0097c000)
        /lib/ld-linux.so.2 (0x0095a000)


库文件libmessage.so不能在任何一个标准搜索路径中找到,而且系统提供的配置文件/etc/ld.so.conf也没有包含一个额外的条目来指定包含该库文件的目录。

需要设置一个环境变量LD_LIBRARY_PATH来制定额外的共享函数库搜索路径,
引用
# export LD_LIBRARY_PATH=`pwd`
# ldd goodbye
        linux-gate.so.1 =>  (0x002ce000)
        libmessage.so => /tmp/cpro/libmessage.so (0x00b0f000)
        libc.so.6 => /lib/libc.so.6 (0x0097c000)
        /lib/ld-linux.so.2 (0x0095a000)
运行程序
引用
# ./goodbye
Goodbye, world!
3
0
分享到:
评论

相关推荐

    linux下GCC编译C程序

    【GCC编译C程序】是Linux环境中开发C语言软件的核心环节。GNU编译器集(GCC),最初称为GNU C编译器,由Richard Stallman在1987年发起,旨在构建符合自由软件理念的编译器,用于构建GNU项目中的其他软件。GCC很快因...

    如何在Linux下用gcc编译c程序

    对于初学者或专业人士而言,掌握如何在Linux环境下使用gcc编译C程序是至关重要的。下面我们将详细探讨这个过程及其相关知识点。 首先,要开始编译C程序,你需要确保你的Linux系统已经安装了GCC。你可以通过运行`gcc...

    arm-linux-gcc编译选项.pdf

    以下是arm-linux-gcc编译选项的详细知识点说明: 1. 编译过程的四个阶段: - 预处理阶段:GCC会对源文件进行预处理,展开宏定义、处理条件编译指令、包含头文件等。 - 编译阶段:经过预处理的源文件会被转化为...

    linux中gcc4.8.5,下载解压即可直接使用,linux系统GCC编译

    Linux中的GCC(GNU Compiler Collection)是开源的、跨平台的编译器套件,用于将C、C++、Fortran、Objective-C等编程语言的源代码编译为可执行文件。GCC 4.8.5是该系列的一个稳定版本,发布于2015年,虽然不是最新版...

    Linux下使用codeblocks交叉编译ARM-LINUX-GCC程序

    Linux 下使用 CodeBlocks 交叉编译 ARM-LINUX-GCC 程序 在这个资源中,我们将学习如何使用 CodeBlocks 在 Linux 平台下交叉编译 ARM-LINUX-GCC 程序。交叉编译是一种在不同的平台之间编译代码的技术,能让开发者在...

    Visual Studio 2010 编译C及一个完整的c程序(可在windows与linux(用gcc编译)平台下使用)

    标题中的“Visual Studio 2010 编译C及一个完整的c程序”指的是使用Microsoft Visual Studio 2010这个集成开发环境(IDE)来编写和编译C语言程序。Visual Studio 2010提供了强大的代码编辑器、调试工具和项目管理...

    linux Gcc 编译详解

    GCC,全称GNU Compiler Collection,是Linux环境下广泛使用的编译器套件,它不仅支持C语言,还支持C++、Fortran、Objective-C等多种编程语言。本文将详细讲解Linux下GCC的编译过程,包括预处理、编译、汇编和链接四...

    ucosii mini2440 arm-linux-gcc 编译

    总之,将UCOSII在Mini2440上用arm-linux-gcc编译并运行,是一项涉及操作系统、处理器架构、嵌入式编程等多方面知识的综合实践。通过这个过程,开发者不仅能掌握UCOSII的使用,还能提升在嵌入式系统开发中的实际操作...

    arm-linux-gcc 裸机程序

    **描述:“这个一个简单的用arm-linux-gcc编译的运行在mini2440上的裸机程序,移植了u-boot的启动代码。但目前只能用supervivi的D功能下载到内存中运行。程序功能:流水灯”** 描述中提供了几个关键信息: 1. **arm...

    Linux下的简单C程序gcc编译、gdb调试。

    Linux下的简单C程序gcc编译、gdb调试。

    LINUX下的GCC编译指南

    GCC 编译指南是 LINUX 下的一种编译工具,主要用于编译 C 语言程序。GCC 编译指南提供了多种参数选项,用于控制编译过程的各个阶段。下面对 GCC 编译指南的使用方法进行详细介绍。 基本用法 GCC 编译指南的基本...

    linux操作系统下C语言编程入门 gcc编译

    ### Linux操作系统下C语言编程入门:gcc编译与调试技术 #### 一、基础知识 在Linux环境下进行C语言编程,需要掌握一系列基础知识和技术,其中包括源程序的编译、Makefile的编写、程序库的链接、程序调试以及头文件...

    gcc编译原理例子文件

    **GCC编译原理详解** GCC(GNU Compiler Collection)是GNU项目的一部分,是一个广泛使用的开源编译器套件,用于将源代码编译成可执行程序。这个压缩包包含的文件展示了GCC编译过程的不同阶段,让我们逐一分析这些...

    arm-linux-gcc-5.4.0交叉编译工具.rar

    ARM-Linux-GCC 5.4.0 是一个专门用于在ARM架构的Linux系统上进行编译的交叉编译工具链。它允许开发者在非ARM平台(如x86架构的个人电脑)上构建适用于ARM处理器的应用程序和库。这个版本的交叉编译器对于那些需要...

    arm-linux-gcc交叉编译工具2

    4. **使用arm-linux-gcc编译**: - 编译选项:在编译时,需要指定目标架构和链接器参数。例如,`arm-linux-gcc -o target_program source_file.c -Iinclude_dir -Llibrary_dir -llibrary_name`。 - 调试选项:为了...

    linux驱动程序编译以及应用程序编译

    编译过程中需要使用交叉编译器 arm-linux-gcc,将驱动程序编译成模块并安装到 Linux 系统中。在本文中,我们将详细介绍 Linux 驱动程序编译和应用程序编译的过程。 一、驱动程序编译成模块 驱动程序编译成模块需要...

    linux安装gcc编译环境所需rpm包

    7. 完成安装后,你就可以使用GCC编译C、C++等语言的程序了。 在实际操作中,"gcc"这个压缩包子文件可能包含了GCC的RPM包,你需要解压并使用zypper安装其中的RPM文件。务必注意,直接使用RPM包可能会遇到依赖关系...

    Linux下用GCC运行C语言源文件的实例

    对于C语言爱好者来说,掌握如何在Linux下使用GCC编译和运行C语言源文件是至关重要的。下面我们将详细探讨这个过程,以及相关的一些知识点。 首先,安装GCC。在大多数Linux发行版中,GCC可能已经预装,如果没有,...

    arm-linux-gcc交叉编译环境安装.pdf

    例如,用户可以使用 arm-linux-gcc 命令来编译一个 C 语言程序。 Arm-Linux-GCC 交叉编译环境安装的优点是可以让开发者在 Linux 系统中编译 Arm 架构的程序,从而实现跨平台编译的功能。 Arm-Linux-GCC 交叉编译...

Global site tag (gtag.js) - Google Analytics