苏嵌嵌入式Linux实训第三天

问题一:1、编译器三级优化分别优化了哪些?
答:DNU编译器提供-O选项供程序优化使用:
-O 提供基础级别的优化
-O2 提供更加高级的代码优化,会占用更长的编译时间
-O3 提供最高级的代码优化
-O4 不优化,这是默认值
第一级:代码调整
代码调整是一种局部的思维方式;基本上不触及算法层级;它面向的是代码,而不是问题; 所以:语句调整,用汇编重写、指令调整、换一种语言实现、换一个编译器、循环展开、参数传递优化等都属于这一级;这个级别试图执行9种单独的优化功能:
-fdefer-pop
-fmerge-constans
-fthread-jumps
-floop-optimize
-fif-conversion: if-then
-fif-conversion2
-fdelayed-branch
-fguess-branch-probability
-fcprop-registers
第二级:新的视角
新的视角强调的重点是针对问题的算法;即选择和构造适合于问题的算法;(冒泡排序还是快排的选择问题是这一级早就应该完成的)很多经典算法都对问题作了一些假设(包括我们当前已经完成的算法实现),而在面对实际问题时“新的视角”提示我们应该重新检视这些假设,并尝试不同的思考问题的角度,寻求适合于问题的新算法; 编译器还试图采用以下几种优化。
10. -fforce-mem
11. -foptimize-sibling-calls
12. -fstrength-reduce
13. -fgcse
14. -fcse-follow-jumps
15. -frerun-cse-after-loop
16. -fdelete-null-pointer-checks
17. -fextensive-optimizations
18. -fregmove
19. -fschedule-insns
20. -fsched-interblock
21. -fcaller-saves
22. -fpeephole2
23. -freorder-blocks
24. -fstrict-aliasing
25. -funit-at-a-time
26. -falign-functions
27. -fcrossjumping
第三级:表驱动状态机
将问题抽象为另一种等价的数学模型或假想机器模型,比如构造出某种表驱动状态机;这一级其实是第二级的延伸,只是产生的效果更加明显,但它有其本身的特点(任何算法和优化活动都可以看作是他的投影);这一级一般可以产生无与伦比的快速程序, 要达到这一级需要大量修炼的;并且思考时必须放弃很多已有的概念或者这些概念不再重要,比如:变量、指针、空间、函数、对象等,剩下的只应该是那个表驱动状态机; 我想把这种境界描述为:空寂中,一些输入驱动着一个带有状态的机器按设定好的最短路线运转着;除此之外have nothing; 既:把解决一个问题的算法看作一个机器,它有一些可变的状态、有一些记忆、有一些按状态运行的规则,然后一些输入驱动这个机器运转;这就是第三级要求的思考优化问题的切入点,也就是寻找一部机器,使它运行经过的路径最短(可能是速度也可能是空间等等) 。编译器还试图采用以下这种优化方式。
28. -finline-functions
29. -fweb
30. -fgcse-after-reload
二.总结gcc静态库和动态库的制作

  程序清单如下:

test.c

1 int add(int a,int b)
2 {
3    retrun a+b;
4 }
5
6 int sub(int a,int b)
7 {
8    retrun a-b;
9 }
10
11 int mul(int a,int b)
12 {
13    retrun a*b;
14 }
15
16 int div(int a,int b)
17 {
18    retrun a/b;
19 }

test.h的内容


1 #ifndef TEST_H
2 #define TEST_H
3 extern int add(int a,int b);
4 extern int sub(int a,int b);
5 extern int mul(int a,int b);
6 extern int div(int a,int b);

main.c文件内容


1 #include<stduo.h>
2 #include<test.h>
3 int main()
4 {
5   int a,b;
6   printf(“please input a and b\n”);
7   scanf("%d %d",&a,&b);
8   printf(“The add:%d\n”,add(a,b));
9   printf(“The sub:%d\n”,sub(a,b));
10   printf(“The mul:%d\n”,mul(a,b));
11   printf(“The div:%d\n”,div(a,b));
12 }

1.使用gcc生成静态库及静态库使用方法:

在此例中,test.c用于编译生成静态库libtest.a,test.h为libtest.a对应的头文件。

第一步:生成test.o目标文件,使用gcc -c test.c -o test.o命令。

第二步:使用ar将test.o打包成libtest.a静态库,使用ar rcs -o libtest.a test.o命令

第三步:生成libtest.a静态库后,可以使用命令ar t libtest.a查看libtest.a文件中包含哪些文件。

第四步:编译main.c,并使用libtest.a静态库,链接时-l参数后不加空格指定所需要链接的库,这里库名是libtest.a,但是只需要给出-ltest即可,ld会以libtest作为库的实际名字。完整的命令为:gcc -o app_static main.c -L. -ltest 或者是gcc -o app_static main.c libtest.a

第五步:运行app_static

直接使用命令./app_static

2.使用gcc生成动态库及使用动态库的方法

第一步:生成test.o目标文件,使用如下命令。在此处需要添加-fPIC参数,该参数用于生成位置无关代码已工生成动态库使用,使用命令:gcc -c -o test.o -fPIC test.c

第二步:使用-shared参数生成动态库,使用如下命令:gcc -shared -o libmyshare.so test.o,上述两个命令可以连在一起,如下所示:gcc -shared -fPIC -o libmyshare.so test.c

第三步:编译main.c,使用libmyshare.so动态库,命令如下gcc -o app_share main.c -L. -lmyshare.使用ldd app_share命令查看app_share使用动态库,如果libmyshare无法找到,直接执行app_share就会出现错误。解决方法:首先使用export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH将当前目录加入LD_LIBRARY_PATH变量中。再次运行ldd app_share

另一种编译main.c,并链接libmyshare.so的方式如下(该方式通过./libmyshare.so直接指定使用当前目录下的libmyshare.so文件),使用命令:gcc -o app_share main.c ./libmyshare.so
  三.总结CMake用法;
答:
变量的用法与调试
定义变量:set 命令,定义normal var、环境变量、cache entry等;
取消定义:unset 命令,取消变量的定义;
使用变量: v a r 引 用 变 量 , {var}引用变量, varENV{var}引用环境变量,在 IF 等语句中直接使用变量名而不通过${}取值;
调试方法:message 命令,可以打印输出;

常见的内置变量: https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html

CMAKE_C_FLAGS: Initialized by the CFLAGS environment variable.
CMAKE_CXX_FLAGS: Initialized by the CXXFLAGS environment variable.
CMAKE_CURRENT_LIST_DIR cmake脚本所在的当前目录.
更多的内置命令可以看前面官方给出的文档链接。

设置头文件搜索路径
include_directories 命令,添加头文件搜索路径,最终就是在生成的Makefile中把头文件搜索目录作为命令行参数传给了编译器。

添加目录下所有源文件
aux_source_directory 命令,找到目录下所有的源文件存到一个变量中。

设置编译目标
add_executable 编译可执行文件目标;
add_library 编译静态或动态库目标,通过STATIC | SHARED来控制;
add_custom_target 目标不是一个真实文件,总会执行到,类似Makefile里的all目标;

设置链接文件和搜索路径
link_directories 链接器的搜索目录;
link_libraries 后续的所有target都会链接;
target_link_libraries 给指定target链接对应的库文件;

设置编译宏和编译选项
add_compile_definitions 在当前目录下传preprocessor definitions给编译器;
target_compile_definitions 给指定的目标传递预编译参数;
add_compile_options 在当前目录下传递任意参数给编译器,预处理定义用前面的add definitions传会更清晰;
target_compile_options 给指定目标传编译参数,目标是之前add的库或可执行文件;
注意一下add_compile_options和CMAKE_CXX_FLAGS的区别:

add_compile_options命令添加的编译选项是针对所有编译器的(包括c和c++编译器);
set命令设置CMAKE_C_FLAGS或CMAKE_CXX_FLAGS变量则是分别只针对c和c++编译器的;
控制语句if/while等的使用
if, 条件执行一些命令;
while 循环执行一些命令;
foreach 对一组list都执行一些命令块;
function 顶一个逻辑块方便后续调用;
return 从文件目录或函数返回;

添加子目录
add_subdirectory 添加要编译的子目录,会加载子目录下CMakeLists.txt。此命令组织大型工程必备。

添加别的CMake脚本
include 为了是CMake脚本更简洁清晰,可以把一些脚本写到别的CMake文件中,include进来用就好。

CMake的命令行接口
cmake命令行接口,cmake命令常常这么用,在工程根目录下新建一个build目录,进入执行cmake …来进行编译。

CMake demo用法举例
一个项目的目录结构如下:

test
├── build
├── CMakeLists.txt
└── src
├── add
│ ├── add.cpp
│ ├── add.h
│ └── CMakeLists.txt
├── include
│ └── sub.h
├── main.cpp
└── sub.cpp
1
2
3
4
5
6
7
8
9
10
11
12
其中项目test根目录CMake文件如下:

cmake_minimum_required(VERSION 3.10)

project(HELLOWORLD)

设置变量:目标可执行文件名

set(TARGET helloworld)

设置编译选项

add_compile_options(
-m64 -Wall -Werror
-O0 -ggdb3
)

添加头文件搜索路径

include_directories(
./src/include
./src/add
)

添加一个目录下的所有源文件

aux_source_directory(./src DIR_SRCS)
message(“src files @dir{}” ${DIR_SRCS})

添加子目录 --> 子目录用来编译共享库 libadd.so

add_subdirectory(src/add)

编译可执行文件

add_executable(${TARGET} D I R S R C S ) t a r g e t l i n k l i b r a r i e s ( {DIR_SRCS}) target_link_libraries( DIRSRCS)targetlinklibraries({TARGET} add)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
子目录add下的CMake文件:

message(“build libadd.so”)
add_library(add SHARED add.cpp)
1
2
代码文件内容十分简单,main.cpp调用了add, sub两个函数,这两个函数分别在add.cpp和sub.cpp实现了。这里通过编译工程把add编译为了共享库so的形式,编译参数则开启了所有告警等。

执行的时候,进入到build目录,cmake … 然后 make 就OK了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值