Flex程序编译

2023-11-17

Makefile三要素:
目标、依赖、命令
详解可见makefile 编写_周北-CSDN博客_makefile 编写

Makefile中常用函数和自动化变量:
wildcard-扩展通配符
例:OBJECTS=$(wildcard *.o)
该找到目标文件下的所有后缀为.c的文件名并将它们全都赋给OBJECT(即,OBJECT是.o文件的集合,并且这个函数中的OBJECTS是个任意命名的变量,但是$(wildcard .o)是这个实现找出.o文件的Makefile函数),要注意的是在wildcard和.o之间是是通过空格隔开的)。
patsubst-替换通配符
obj=$(patsubst %, $(LIBPATH)/%/$(LIB_TYPE), $(LINKDIRS))
该函数的功能是在LINKDIRS(第三个参数的集合)中取出各个单元(库所在目录名), 将所有包含第一个参数的部分替换成第二个参数的部分。要注意的是在这个函数中patsubst 和%之间是没有逗号将它们两个隔开的,它们两个之间只有空格,%, $(LIBPATH)/%/$(LIB_TYPE), $(LINKDIRS)之间则使用逗号隔开。
foreach-循环函数
也可使用类似于Shell的for循环语句:

for name in $(FILES); do \  
    echo "$$name"; \  
done  

注意, 在makefile中的shell变量要用2个$号表示变量名称
其他函数可参见makefile中常用函数_.-CSDN博客_makefile常用函数

Makefile三个自动化变量:
$@    规则中的目标集合,在模式规则中,如果有多个重复目标的话,“$@” 表示匹配模式中定义的目标集合
$%    当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,那么其值为空
$<    依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<” 就是符合模式的一系列的文件集合,多次调用则向后顺移读取
$?    所有比目标新的依赖目标集合,以空格分开
$^    所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个文件“$^” 会去除重复的依赖文件,值保留一份
$+    和“$^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件
$*    这个变量表示目标模式中"%"及其之前的部分,如果目标是式为a.%.c,那么“$*”就是test/a.test

makefile允许命令行传参,通常用于指定宏编译
实例解析可见一点一点学写Makefile(4) - 编译时指定宏参数_qq849635649的博客-CSDN博客_make 指定宏
makefile可以使用自动化构建工具CMake生成

Makefile中常见预定义变量
AR  库文件维护程序的名称,默认值为ar,创建静态库.a
AS  汇编程序的名称,默认值为as
CC  C编译器的名称,默认值为cc
CPP C预编译器的名称,默认值为$(CC) –E
CXX C++编译器的名称,默认值为g++
FC  FORTRAN编译器的名称,默认值为f77
RM  文件删除程序的名称,默认值为rm –f
ARFLAGS 库文件维护程序的选项,无默认值
ASFLAGS 汇编程序的选项,无默认值
CFLAGS  C编译器的选项,无默认值
CPPFLAGS C预编译的选项,无默认值
CXXFLAGS C++编译器的选项,无默认值
FFLAGS   FORTRAN编译器的选项,无默认值

GCC编译选项CFLAGS参数
-c    用于把源码文件编译成.o对象文件,不进行链接过程
-o    用于连接生成可执行文件,在其后可以指定输出文件的名称
-g    用于在生成的目标可执行文件中,添加调试信息,可以使用GDB进行调试
-Idir    用于把新目录添加到include路径上,可以使用相对和绝对路径,“-I.”、“-I./include”、“-I/opt/include”
-Wall    生成常见的所有告警信息,且停止编译,具体是哪些告警信息,请参见CC手册,一般用这个足矣!
-w    关闭所有告警信息
-O    表示编译优化选项,其后可跟优化等级0\1\2\3,默认是0,不优化
-fPIC    用于生成位置无关的代码
-v    (在标准错误)显示执行编译阶段的命令,同时显示编译器驱动程序,预处理器,编译器的版本号

GCC链接选项LDFLAGS参数
-llibrary    链接时在标准搜索目录中寻找库文件,搜索名为liblibrary.a 或 liblibrary.so
-Ldir    用于把新目录添加到库搜索路径上,可以使用相对和绝对路径,“-L.”、“-L./include”、“-L/opt/include”
-Wl,option    把选项 option 传递给连接器,如果 option 中含有逗号,就在逗号处分割成多个选项
-static    使用静态库链接生成目标文件,避免使用共享库,生成目标文件会比使用动态链接库大
另外,LDFLAGS告诉链接器从哪里寻找库文件,LIBS告诉链接器要链接哪些库文件。

接下来利用一个简单地实例进行说明,安装Flex编译一个文本识别的小demo。Flex的源程序(定义词法解析处理规则)需要经过Flex工具形成完成的词法解析程序,最后和Main程序链接到一起。
编写testMain.c

#include <stdio.h>

extern int yylex();

extern int chars;
extern int words;
extern int lines;

void main(int argc, char **argv)
{
    yylex();
    printf("line: %d, word: %d, char: %d\n", lines, words, chars);
}

编写testFlex.l

%{
    int chars = 0;
    int words = 0;
    int lines = 0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
\n        { chars++; lines++; }
.         { chars++; }
%%

根据编译过程,编写一个直观的Makefile

ECHO = echo       #将编译器选项定义为变量,提高makefile文件的可移植性           
CC   = gcc 
FLEX = flex
 
target: start testDemo            #make命令默认执行第一个target及其依赖项
    @$(ECHO) compiling is finished!
start:
    @$(ECHO) compiling......
testDemo: testMain.o testFlex.o
    $(CC) -o testDemo testMain.o testFlex.o -lfl -Wall
testMian.o: testMain.c
    $(CC) -c testMian.c
testFlex.o: testFlex.c
    $(CC) -c testFlex.c 
testFlex.c: testFlex.l
    $(FLEX) -o testFlex.c testFlex.l 
clean:               #make clean执行非第一个target子程序的clean target
    @$(ECHO) cleaning......
    rm testFlex.c ./*.o testDemo

根据编译过程,编写一个使用自动化变量的Makefile

ECHO = echo       #将编译器选项定义为变量,提高makefile文件的可移植性           
CC   = gcc 
FLEX = flex

OBJECTS = testMain.o
OBJECTS += testFlex.o

TARGET = ./testDemo
CFLAGS = -Wall
LIBS   = -lfl

TARGET: $(OBJECTS)  #make命令默认执行第一个target及其依赖项
    $(CC) -o $(TARGET) $(OBJECTS) $(LIBS) $(CFLAGS)
    @$(ECHO) compiling is finished!

#.c.o :   一种旧格式写法
%.o : %.c
    $(CC) -o $@ -c $<

#.l.c :
%.c : %.l
    $(FLEX) -o $@ $<
 
clean:               #make clean执行非第一个target子程序的clean target
    @$(ECHO) cleaning......
    rm $(OBJECTS) $(TARGET) -f

.PHONY : clean

在clean目标中需要配合使用伪目标声明,这个伪目标声明是指当当前路径下含有以clean命令的文件或者是目录的时候,则在使用命令make clean的时候,就会导致结果无法执行。
解决这种问题,只需要在makefile中加入一个伪目标声明即可,格式为 .PHONY.clean。
具体说明可见makefile中的all和.PHONY的作用-andyhzw-ChinaUnix博客
另外,关于Makefile特殊目标的详细说明可见Makefile的特殊目标 | 学步园

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flex程序编译 的相关文章

  • 将 jar 作为 Linux 服务运行 - init.d 脚本在启动应用程序时卡住

    我目前正在致力于在 Linux VM 上实现一个可运行的 jar 作为后台服务 我已经使用了找到的例子here https gist github com shirish4you 5089019作为工作的基础 并将 start 方法修改为
  • 如何通过ssh检查ubuntu服务器上是否存在php和apache

    如何通过ssh检查Ubuntu服务器上apache是 否安装了php和mysql 另外如果安装的话在哪个目录 如果安装了其他软件包 例如 lighttpd 那么它在哪里 确定程序是否已安装的另一种方法是使用which命令 它将显示您正在搜索
  • “make install”将库安装在 /usr/lib 而不是 /usr/lib64

    我正在尝试在 64 位 CentOS 7 2 上构建并安装一个库 为了这个目的我正在跑步 cmake DCMAKE BUILD TYPE Release DCMAKE INSTALL PREFIX usr DCMAKE C COMPILER
  • 需要一些建议来开始在 ARM(使用 Linux)平台上编程

    我 也许 很快就会在托管 Linux 发行版的 ARM 平台上工作 我不知道哪个发行版 我知道该项目涉及视频流 但我无法告诉你更多信息 其实我只收到通知 还没见到任何人 我从来没有在这样的平台上工作过 所以我的想法是在项目开始之前进行测试
  • php exec 返回的结果比直接进入命令行要少

    我有一个 exec 命令 它的行为与通过 Penguinet 给 linux 的相同命令不同 res exec cd mnt mydirectory zcat log file gz echo res 当将命令直接放入命令行时 我在日志文件
  • 如何减去两个 gettimeofday 实例?

    我想减去两个 gettimeofday 实例 并以毫秒为单位给出答案 这个想法是 static struct timeval tv gettimeofday tv NULL static struct timeval tv2 gettime
  • waitpid() 的作用是什么?

    有什么用waitpid 它通常用于等待特定进程完成 或者如果您使用特殊标志则更改状态 基于其进程 ID 也称为pid 它还可用于等待一组子进程中的任何一个 无论是来自特定进程组的子进程还是当前进程的任何子进程 See here http l
  • Linux:如何设置进程的时区?

    我需要设置在 Linux 机器上启动的各个进程的时区 我尝试设置TZ变量 在本地上下文中 但它不起作用 有没有一种方法可以使用与系统日期不同的系统日期从命令行运行应用程序 这可能听起来很愚蠢 但我需要一种sandbox系统日期将被更改的地方
  • 在两次之间每分钟执行一次 Cronjob

    我需要在 crontab 中每分钟运行一个 bash 脚本8 45am and 9 50am每天的 Code 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 8 home pull sh gt ho
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost
  • Urwid:使光标不可见

    我正在使用 urwid 它是一个用于在 ncurses 中设计终端用户界面的 Python 框架 但有一件事我在 urwid 中无法做到 而这在 Curses 中很容易做到 使光标不可见 现在 选择按钮时光标是可见的 而且看起来很丑 有办法
  • 高效的内存屏障

    我有一个多线程应用程序 其中每个线程都有一个整数类型的变量 这些变量在程序执行期间递增 在代码中的某些点 线程将其计数变量与其他线程的计数变量进行比较 现在 我们知道在多核上运行的线程可能会无序执行 一个线程可能无法读取其他线程的预期计数器
  • 在 Mac OSX 上交叉编译 x86_64-unknown-linux-gnu 失败

    我尝试将我的 Rust 项目之一编译到 x86 64 unknown linux gnu 目标 cargo build target x86 64 unknown linux gnu Compiling deployer v0 1 0 fi
  • Linux 上的基准测试程序

    对于一项任务 我们需要使用不同的优化和参数来对我们的实现进行基准测试 有没有一种可行的方法可以在Linux命令行 我知道时间 上使用不同的参数对小程序进行基准测试 从而为我提供CSV或类似内容的时间数据 输出可能类似于 Implementa
  • 警告:请求的映像平台 (linux/amd64) 与检测到的主机平台 (linux/arm64/v8) 不匹配

    警告 请求的映像平台 linux amd64 与检测到的主机平台 linux arm64 v8 不匹配 并且未请求特定平台 docker 来自守护程序的错误响应 无法选择具有功能的设备驱动程序 gpu 我在 mac 上尝试运行此命令时遇到此
  • 当用户按下打印时运行脚本,并且在脚本结束之前不开始假脱机(linux,cups)

    我需要做的是结合用户按下打印来执行 python 程序 脚本 并且在该程序退出之前不要让打印作业假脱机 原因是打印驱动程序不是开源的 我需要更改用户设置 在本例中是部门 ID 和密码 通常是每个用户 但因为这是一个信息亭 具有相同帐户的不同
  • Awk - 计算两个文件之间的每个唯一值和匹配值

    我有两个文件 首先 我尝试获取第 4 列中每个唯一字段的计数 然后匹配第二个文件的第二列中的唯一字段值 File1 第 4 列的每个唯一值和 File2 第 2 列包含我需要在两个文件之间匹配的值 所以本质上 我试图 gt 如果 file2
  • 如何在 GNU/Linux 上设置 Subversion (SVN) 服务器 - Ubuntu [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一台运行 Ubuntu 的笔记本电脑 我想将其用作 Subversion 服务器 既让我自己在本地承诺 也让其他人远程承诺 要使其
  • Gearman,php 扩展问题:使用终端在 .. 中找不到类“GearmanWorker”,但可以在浏览器上使用

    我最近在 ubuntu 10 04 上安装了 gearman 并安装了它的 pecl 扩展 现在 当我在浏览器中运行一个 php 文件时 其中包含 client new GearmanWorker die var Dump client I
  • 嵌入式linux编写AT命令

    我在向 GSM 模块写入 AT 命令时遇到问题 当我使用 minicom b 115200 D dev ttySP0 term vt100 时它工作完美 但我不知道如何在 C 代码中做同样的事情 我没有收到任何错误 但模块对命令没有反应 有

随机推荐