linux源码安装软件系列1

linux软件安装

在windows安装软件是极其简单的事,无非就是下载,然后一路点击“下一步”即可。而在linux装软件就没那么简单了,尤其是对于新手而言,往往会手足无措,觉得linux很不好用。可一旦习惯了,就会惊叹于linux的强大,安装软件可以简单地用一句命令行解决从下载到安装的整个流程,比windows下的一键安装还要轻爽。也可以自己到官网下载源码,自己编译,甚至修改源码,真正自定义安装软件。

本系列文章主要讲解通过源码安装软件的原理以及方法。

我们知道,不管是windows,还是linux,最终能执行的都是二进制文件,而我们的代码是用编程语言写的文本文件,要转换成操作系统能识别的二进制码就需要编译器。

以下用实例演示编译源码的操作流程

编译单一文件

新建c语言文件:hello.c

#include <stdio.h>
int main(void)
{
    printf("Hello World\n");
}
[senlong@linux ~]$ gcc hello.c 
[senlong@linux ~]$ ll hello.c a.out 
-rwxrwxr-x 1 senlong senlong 8512 7月  27 08:44 a.out
-rw-rw-r-- 1 senlong senlong   67 7月  27 08:44 hello.c
[senlong@linux ~]$ ./a.out
Hello World

以上实例演示了hello.c源码文件经由gcc命令编译生成a.out可执行文件

相关术语解释:

  • 源码文件:即程序员写的源代码文件(hello.c)
  • 编译器:将便于人编写,阅读,维护的高级计算机语言所写作的源码程序,翻译为计算机能解读、运行的低阶机器语言的程序(gcc)
  • 可执行文件:操作系统能直接识别,可直接执行的二进制文件(a.out)

可执行文件与普通文本文件可通过file指令识别:

[senlong@linux ~]$ file hello.c
hello.c: C source, ASCII text # 普通文本文件
[senlong@linux ~]$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=29c4c64ff2985490bb17a37ef188574a0009b3da, not stripped # 可执行的二进制文件

编译多个文件

默认情况下,使用gcc编译输出的二进制文件是a.out, 我们可以将gcc的编译行为拆分成两个步骤:

  • gcc -c filename.c 生成目标文件(object file)
  • gcc -o filename.o 生成可执行文件
[senlong@linux ~]$ gcc -c hello.c
[senlong@linux ~]$ ll hello*
-rw-rw-r-- 1 senlong senlong   67 7月  27 08:44 hello.c
-rw-rw-r-- 1 senlong senlong 1496 7月  27 08:53 hello.o # object file
[senlong@linux ~]$ gcc -o hello hello.o
[senlong@linux ~]$ ll hello*
-rwxrwxr-x 1 senlong senlong 8512 7月  27 08:54 hello # 二进制文件
-rw-rw-r-- 1 senlong senlong   67 7月  27 08:44 hello.c
-rw-rw-r-- 1 senlong senlong 1496 7月  27 08:53 hello.o
[senlong@linux ~]$ ./hello
Hello World

那么问题来了,既然可以一步到位用一个命令生成可执行文件,为什么还要拆分成两步呢?

继续以下实例:

thanks.c

#include <stdio.h>
int main(void)
{
    printf("Hello World\n");
    thanks_2();
}

thanks_2.c

#include <stdio.h>
void thanks_2(void)
{
    printf("Thank you!\n");
}
[senlong@linux ~]$ gcc -c thanks.c thanks_2.c 
[senlong@linux ~]$ ll thanks*
-rw-rw-r-- 1 senlong senlong   71 7月  27 08:57 thanks_2.c
-rw-rw-r-- 1 senlong senlong 1504 7月  27 09:04 thanks_2.o
-rw-rw-r-- 1 senlong senlong   83 7月  27 08:56 thanks.c
-rw-rw-r-- 1 senlong senlong 1560 7月  27 09:04 thanks.o
[senlong@linux ~]$ gcc -o thanks thanks.o thanks_2.o
[senlong@linux ~]$ ll thanks*
-rwxrwxr-x 1 senlong senlong 8584 7月  27 09:05 thanks
-rw-rw-r-- 1 senlong senlong   71 7月  27 08:57 thanks_2.c
-rw-rw-r-- 1 senlong senlong 1504 7月  27 09:04 thanks_2.o
-rw-rw-r-- 1 senlong senlong   83 7月  27 08:56 thanks.c
-rw-rw-r-- 1 senlong senlong 1560 7月  27 09:04 thanks.o
[senlong@linux ~]$ ./thanks
Hello World
Thank you!

此时我们再来更改thanks_2.c文件:

#include <stdio.h>
void thanks_2(void)
{
    printf("Thank you very much!\n");
}

现在我们只需要单独编译thanks_2.c文件,再将两个目标文件联结重新生成可执行文件。不需要再去编译thanks.c

[senlong@linux ~]$ gcc -c thanks_2.c
[senlong@linux ~]$ gcc -o thanks thanks.o thanks_2.o
[senlong@linux ~]$ ./thanks 
Hello World
Thank you very much!

之所以要生成目标文件,是因为源码文件很多时候不是单一文件,如果其中有一个文件变化了,只需要重新编译此文件,而不用全部文件再次编译

引用外部函数库

函数库指封装好的实现一定功能的程序。可以在别的程序直接引用,如以下实例:计算sina值,调用了sin()函数

sina.c

#include <stdio.h>
#include <math.h>
int main(void)
{
    float value;
    value = sin ( 3.14 / 2 );
    printf("%f\n",value);
}
[senlong@linux ~]$ gcc sina.c
[senlong@linux ~]$ ./a.out
1.000000

以上介绍了编译源码的基本流程,可以很明显地看出,当我们的文件量大时,如有几百个、几千个文件时,如果还是按照以上这种手工编译的方式,那linux就不好玩了。下篇文章将介绍快速编译的方式。

敬请关注我的账号。

本文借鉴于鸟哥linux

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏林德熙的博客

git subtree pull 错误 Working tree has modifications

git subtree 是不错的东西,用于 git 管理子项目。 本文记录我遇到问题和翻译网上的答案。

1431
来自专栏大内老A

学习ASP.NET Core, 怎能不了解请求处理管道[5]: 中间件注册可以除了可以使用Startup之外,还可以选择StartupFilter

中间件的注册除了可以借助Startup对象(DelegateStartup或者ConventionBasedStartup)来完成之外,也可以利用另一个叫做St...

3477
来自专栏Java后端技术

解决jetty7.0.pre5启动时报ClassNotFoundException: javax.interceptor.InvocationContext异常的问题

一.背景介绍:最近项目在使用maven命令行运行jetty服务器时出现ClassNotFoundException: javax.interceptor.Inv...

781
来自专栏IT技术精选文摘

Nginx模块之Filter解析

过滤模块简介 执行时间和内容 过滤(filter)模块是过滤响应头和内容的模块,可以对回复的头和内容进行处理。它的处理时间在获取回复内容之后,向用户发送响...

2789
来自专栏社区的朋友们

深入浅出 Nodejs( 二 ):Nodejs 文件模块机制

本篇教程关于Nodejs的文件模块机制,具体讲CommonJs规范以及Nodejs文件模块的实现原理。

5182
来自专栏Golang语言社区

Golang语言社区--【游戏服务器知识】多线程并发

引言:上篇文章说到了多进程并发式的服务端模型,如上一篇文章所述,进程的频繁创建会导致服务器不堪负载,那这一篇博客主要讲述的是线程模型和线程池的方式来提高服务端的...

3424
来自专栏高性能分布式系统设计

Go的PCRE包装在启用JIT的时候遇到的问题和解决方案

用CGO包装C的库, 如果启用了JIT的话,会有一些问题. 例如pcre用了JIT动态生成代码并JIT代码引用里自己线程的JIT Stack数据. 这时会有一个...

3057
来自专栏程序员宝库

linux 常用指令

1.查看目录下有什么文件信息 ls //list查看当前目录下有什么文件 ls -l或ls ll //list -list 通过详...

3188
来自专栏PHP在线

拒绝重复造轮子,用composer搞自己的框架(2)

久负盛名的 CodeIgniter 框架是很多人的 PHP 开发入门框架,同样也是我开始学习如何从头构建一个网站的框架。在 CI中我学到了很多,其中对 MVC ...

3839
来自专栏小夜博客

LNMP1.3 安装 fileinfo 组件

3919

扫码关注云+社区

领取腾讯云代金券