苏嵌嵌入式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
    评论
项目开发环境 Linux+Arm53+C语言   项目需求    功能类别 功能名称 描述 家电控制模块 1、空调控制模块 信息显示 显示当前室内温度 自动控制 设置空调在某温度下自动开、关  2、风扇控制模块 状态显示 风扇开、关 自动控制 设置风扇的档数 3、灯光控制模块 状态控制 灯光的开/关控制 亮度 正常、节能  4、窗帘控制模块 自动开/关 根据室外的亮度自动开启/关闭窗帘 手动开/关 读取当前窗帘状态,手动开启/关闭 监控模块  1、烟感监控 自动控制 超过限量烟雾浓渡报警  2、红外监控 自动控制 有人非法闯进报警  3、报警功能 自动控制 打开、关闭  4、GPRS模块 信息收发 当有报警信息的时候,系统会自动将警报信息发送到指定的手机号码。 信息设定 设定接收信息的手机号  5、访客视频对讲 状态显示 观察访客信息、自定义门锁开、关 娱乐模块  1、收音机 状态控制 开、关 自定义 更换频道 自动调节声音 增大、减小  2、家庭影院 灯光控制 亮度效果调节 自动调节声音 增大、减小  3、音频播放 状态控制 开、关 自动调节声音 增大、减小 自定义模式 选择播放、随机播放、顺序播放、列表循环  4、数码相册 状态控制 开、关 自定义模式 选择播放、随机播放、顺序播放、列表循环 场景切换  1、在家模式 状态控制 家居电器开关、灯光亮度、监控状态  2、离家模式    项目源码结构:     |--bin            脚本目录         |--tar.sh     项目打包脚本     |--data           数据目录     |--include        头文件         |--beep.h     蜂鸣器模块         |--bmp.h      BMP图模块         |--config.h   项目配置文件         |--file.h     文件操作模块         |--jpeg.h     JPG图模块         |--led.h      LED模块         |--mp3.h      音频模块         |--mplayer.h  音频库模块         |--res.h      资源配置文件         |--tslib.h    触摸模块         |--ui.h       UI模块         |--vedio.h    视频模块     |--lib            库文件     |--pic            资源图片         |--icon       应用图标         |--ui         UI文件     |--shortcut       项目效果图     |--ext            第三方库         |--driver     驱动         |--lib        第三方库     |--src            代码目录         |--main.c     主程序         |--Makfile    自动编译脚本 --------------------- 作者:qq_39188039 来源:CSDN 原文:https://blog.csdn.net/qq_39188039/article/details/83751526 版权声明:本文为博主原创文章,转载请附上博文链接!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值