设为首页 收藏本站
查看: 858|回复: 0

[经验分享] ubuntu下面几种编译器

[复制链接]

尚未签到

发表于 2017-11-19 21:25:01 | 显示全部楼层 |阅读模式
  本文档主要总结了集中编译器的使用方法:主要包括bazel,gcc,g++
  1.gcc
  编译语言:C/C++/FORTRAN/JAVA/OBJC/ADA


  • 语法:gcc(选项) (参数)
  • 选项:  



-o:指定生成的输出文件;
-E:仅执行编译预处理;
-S:将C代码转换为汇编代码;
-wall:显示警告信息;
-c:仅执行编译操作,不进行连接操作。

  • 参数:
  C源文件:指定C语言源代码文件。


  • 实例



#假设源程序文件名为test.c
#无选项编译链接
gcc test.c
#将test.c预处理,汇编,编译并链接形成可执行文件,这里未指定输出文件,默认输出为a.out。
#选项 -o
gcc test.c -o test
#将test.c预处理,汇编,编译并链接形成可执行文件test。
#-o选项用来指定输出的文件名。
#选项 -E
gcc -E test.c -o test.i
#将test.c预处理输出test.i文件。
#选项-S
gcc -S test.i
#将预处理输出文件test.i汇编成test.s文件。
#选项-c
gcc -c test.s
#将汇编输出文件test.s链接成最终可执行文件test。
#无选项链接
gcc test.o -o test
#将编译出文件test.o链接成最终可执行文件test。
#选项 -O
gcc -O1 test.c -o test
#使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但是编译时间越长。

  • 多源文件的编译方法
  如果有多个源文件,有两种编译方法:



#方法一:多个文件一起编译
gcc testfun.c test.c -o test
#将testfun.c和test.c分别编译后链接成test可执行文件。
#方法二:分别编译各个源文件,之后对编译后输出的目标文件链接。
gcc -c testfun.c #将testfun.c编译成testfun.o
gcc -c test.c     #将test.c编译成test.o
gcc -o testfun.o test.o -o test  #将testfun.c和test.c链接成test
  注:第一种方法编译时需要所有文件重新编译
  第二种方法可以重新编译修改的文件,未修改的文件不要重新编译。


GCC可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言的程序

来自: http://man.linuxde.net/gcc  2.g++


  • g++是linux下c++的编译器,在执行编译工作的时候,总共需要4步:
  (1)预处理,生成*.i的文件;
  (2)将预处理后的文件不转换成汇编语言,生成文件*.s;

  (3)由汇编变为目标代码(机器代码)生成*.o的文件;
  (4)连接目标代码,生成可执行程序。


  • g++编译c++经常使用的参数



#-c:只编译,不连接
g++ -c helloworld.cpp
#只生成helloworld.o不连接
#-o:指定输出文件名
g++ -c helloworld -o abc.o
#默认是生成helloworld.o,用-o abc.o以后,就生成就是abc.o
#-I:附加一个包含头文件的路径。
g++ helloworld.cpp -I"/usr/helloworld/include"
#-l(小L):附一个库
g++ helloworld.cpp -labc
#使用libabc.so
# -L:添加一个库的路径
g++ hello.cpp -L"/usr/hello/lib" -labc
#-shared:生成动态库文件
g++ -shared hello.cpp -o libhello.so

  • 调用动态库的时候有几个问题会经常用到,有时候,明明已经库的头文件所在目录通过include进来了,库所在文件通过“-L”参数引导,并指定了“-l”的库名,但通过ldd命令查看时,就是死活找不到你指定链接的
  so文件。其实编译链接上了共享库不代表执行时可以找到。所以“-L“什么的对执行没有用,你需要指明共享库的路径。方法有三个:
  (1)修改LD_LIBRARY_PATH,指明共享库的路径。LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。在终端下使用如下命令:
  export LD_LIBRARY_PATH = your lib dir export
  (2)通过/etc/ld.so.conf文件来指定动态库的目录。然后运行ldconfig命令更新搜索共享库的路径。通常这个做法就可以解决库无法链接的问题并且一劳永逸。
  (3)把库文件拷贝到/lib下,然后ldconfig就ok了。这个方法有的取巧,且破坏原库文件的纯洁性,不推荐。


  • linux下文件的类型是不依赖于其后缀名的,但是一般讲来:
  *.o:是目标文件,相当于windows中的*.obj文件
  *.so为共享库,是shared object,用于动态连接的,和dll差不多
  *.a为静态库,是好多个*.o合在一起,用于静态连接
  *.la为libtool自动生成的一些共享库,主要是记录了一些配置信息
  3.bazel
  参考:http://blog.163.com/wujiaxing009@126/blog/static/71988399201751110532137/


  • 特点:
  (1)多语言支持
  JAVA/Objective-C和C++
  (2)高级构建描述语言
  项目是使用一种叫BUILD的语言来描述的,它是一种简简洁的文本语言,它把一个项目是为一个集合,这个集合由一些互相关联的库,二进制文件和测试用例组成。相反,像Make这样的工具,需要去描述每一个文件如何调用编译器。
  (3)多平台支持
  同一套工具和相同的BUILD文件可以用来为不同的体系结构构建软件,甚至是不同的平台。在google,bazel被同时用在数据中心系统中的服务器应用和手机端的移动应用上。
  (4)可重复性
  在BUILD文件中,每个库,测试用例和二进制文件都需要明确指定它们的依赖关系。当一个源文件被修改时,bazel凭这些依赖关系来判断哪些部分需要重新构建,以及那些任务可以并行进行。这就是意味着所有构建都是增量的,并且相同构建总是产生一样的结果。
  (5)可伸缩性
  bazel可以处理大型项目,在google,一个服务器软件由十几万行代码是很常见的,在什么都不改的前提下重新构建这样一个项目,大概需要200毫秒。


  • bazel构建C++项目
  (1)使用工作区
  bazel builds应该在一个工作区内运行,这个工作区应该包括源代码和build输出目录的符号链接(如:bazel-bin、bazel-out)。工作区目录的位置是可以随意的,但是工作区的根目录必须包含一个名为WORKSPACE的工作区配置问价,工作区配置文件可以是一个空文件,也可以包含引用外表不构建输出所需的依赖关系,在一个工作区内,可根据需求共享多个项目。
  (2)创建Build文件
  bazel通过检查BUILD文件可以知道哪些目标文件被创建在项目中,这些BUILD文件采用与Python相似的语法所写,这种语言通常是一系列规则的声明,每个规则制定相应的输入、输出以及实现输入到输出的方法。
  (3)通过一个例子学习
  1)建立工作区
  假设有个项目,对应于~/gitroot/my-project/目录,先创建一个空的~/gitroot/my-project/WORKSPACE工作区配置文件,用于表示这是Bazel项目对应的根目录。创立一个hello world工程。



└── my-project
├── lib
│   ├── BUILD
│   ├── hello-greet.cc
│   └── hello-greet.h
├── main
│   ├── BUILD
│   ├── hello-time.cc
│   ├── hello-time.h
│   └── hello-world.cc
└── WORKSPACE
  2)创建源文件



$ # If you're not already there, move to your workspace directory.
$ cd ~/gitroot/my-project #进入项目根目录
$ mkdir ./main    #创建一个main 的文件夹
$ cat > main/hello-world.cc <<'EOF' #在main文件夹中创建一个名为hello-world.cc的文件,并以EOF作为Linux创建文件结束的标志
#include "lib/hello-greet.h" #include lib中的hello-greet.h
#include "main/hello-time.h" #include main文件夹中的hello-time.h,而hello-time.cc则为hello-time.h的实现
#include <iostream> #标准库
#include <string>
int main(int argc, char** argv) {
   std::string who = "world";
   if (argc > 1) {
     who = argv[1];
   }
   std::cout << get_greet(who) <<std::endl;
   print_localtime();
   return 0;
}
EOF
$ cat > main/hello-time.h <<'EOF' #声明hello-time.cc是干什么事情的
#ifndef MAIN_HELLO_TIME_H_
#define MAIN_HELLO_TIME_H_
void print_localtime();

#endif
EOF
$ cat > main/hello-time.cc <<'EOF'#具体hello-time.cc是怎么实现的
#include "main/hello-time.h"
#include <ctime>
#include <iostream>
void print_localtime() {
   std::time_t result = std::time(nullptr);
   std::cout << std::asctime(std::localtime(&result));
}
EOF
$ mkdir ./lib
$ cat > lib/hello-greet.h <<'EOF'
#ifndef LIB_HELLO_GREET_H_
#define LIB_HELLO_GREET_H_
#include <string>
std::string get_greet(const std::string &thing);

#endif
EOF
$ cat > lib/hello-greet.cc <<'EOF'
#include "lib/hello-greet.h"
#include <string>
std::string get_greet(const std::string& who) {
   return "Hello " + who;
}
EOF
  3)添加BUILD文件
  从上面的源代码可知,main/hello-world.cc要用到lib/hello-greet.h和main/hello-time.h。首先在lib目录下为hello-greet.cc创建BUILD.



cc_library(
     name = "hello-greet", #要BUILD的文件的名字
     srcs = ["hello-greet.cc"],#脚本
     hdrs = ["hello-greet.h"],#头文件
     visibility = ["//main:__pkg__"],
)
  注意:visibility = ["//main:__pkg__"]表示hello-greet对于main/BUILD是可见的。
  接下来在main目录下创建BUILD文件:



cc_library(
     name = "hello-time",
     srcs = ["hello-time.cc"],
     hdrs = ["hello-time.h"],
)

cc_binary(
     name = "hello-world",
     srcs = ["hello-world.cc"],
     deps = [
         ":hello-time",
         "//lib:hello-greet",
     ],
)
  注意:当依赖的包在同一个目录下,只需要用:hello-time,当依赖的包在不同的目录下,需要用全路径://lib:hello-greet
  现在可以建立hello world的c++二进制程序了:



$ bazel build main:hello-world
INFO: Found 1 target...
Target //main:hello-world up-to-date:
   bazel-bin/main/hello-world
INFO: Elapsed time: 2.869s, Critical Path: 1.00s
$ ./bazel-bin/main/hello-world
Hello world
Thu Jun 23 18:51:46 2016
$ ./bazel-bin/main/hello-world Bazel
Hello Bazel
Thu Jun 23 18:52:10 2016
  ok!成功建立了第一个bazel项目!
  4)传递依赖(Transitive includes)
  如果一个文件包含一个头文件,那么这个文件的规则也应该依赖与头文件的库,相反的,只有直接依赖需要被指定为依赖。例如,假设sandwich.h包括bread.h,而且bread.h包括flour.h,sandwich.h不包括flour.h,因此这个BUILD文件应该是这样:



cc_library(
     name = "sandwich",
     srcs = ["sandwich.cc"],
     hdrs = ["sandwich.h"],
     deps = [":bread"],
)

cc_library(
     name = "bread",
     srcs = ["bread.cc"],
     hdrs = ["bread.h"],
     deps = [":flour"],
)

cc_library(
     name = "flour",
     srcs = ["flour.cc"],
     hdrs = ["flour.h"],
)
  在这里,sandwich库依赖于bread库,而bread库依赖于flour库。
  5)添加包含路径(adding include paths)
  有时候不能(或者不愿意)让依赖的文件包含咋工作区根目录的路径,现有的库可能已经拥有了包括与工作空间不匹配路径的目录。例如,假设有如下的目录结构:



└── my-project
     ├── third_party
     │   └── some_lib
     │       ├── BUILD
     │       ├── include
     │       │   └── some_lib.h
     │       └── some_lib.cc
     └── WORKSPACE
  bazel希望some_lib.h被包含在third_party/some_lib/include/some_lib.h中,但假定some_lib.cc要依赖于include/some_lib.h。为了使包含路径有效, third_party/some_lib/BUILD需要指定some_lib是一个包含目录:



cc_library(
     name = "some_lib",
     srcs = ["some_lib.cc"],
     hdrs = ["some_lib.h"],
     copts = ["-Ithird_party/some_lib"],
)
  这对外部的依赖尤其有用,因为它们的头文件,否则必须被包含于外部/ [库名称]/前缀。
  6)包含外部库
  7)编译并运行c++测试程序
  8)在预编译上添加依赖

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-408668-1-1.html 上篇帖子: Pycharm ubuntu下输入中文 下篇帖子: Ubuntu 16.04 Matlab2015b安装
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表