使用 flex-lexer 和 cmake 构建错误

build error using flex-lexer and cmake

我正在学习 cmake 和 flex-lexer,但根据 make 的错误消息,我遇到错误代码为 2 的构建问题:

$ make
/usr/bin/cmake -H/home/dac/ClionProjects/openshell -B/home/dac/ClionProjects/openshell --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/dac/ClionProjects/openshell/CMakeFiles /home/dac/ClionProjects/openshell/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/dac/ClionProjects/openshell'
make -f CMakeFiles/lemon.dir/build.make CMakeFiles/lemon.dir/depend
make[2]: Entering directory '/home/dac/ClionProjects/openshell'
cd /home/dac/ClionProjects/openshell && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell/CMakeFiles/lemon.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/dac/ClionProjects/openshell'
make -f CMakeFiles/lemon.dir/build.make CMakeFiles/lemon.dir/build
make[2]: Entering directory '/home/dac/ClionProjects/openshell'
make[2]: Nothing to be done for 'CMakeFiles/lemon.dir/build'.
make[2]: Leaving directory '/home/dac/ClionProjects/openshell'
/usr/bin/cmake -E cmake_progress_report /home/dac/ClionProjects/openshell/CMakeFiles  1
[ 14%] Built target lemon
make -f CMakeFiles/openshell.dir/build.make CMakeFiles/openshell.dir/depend
make[2]: Entering directory '/home/dac/ClionProjects/openshell'
/usr/bin/cmake -E cmake_progress_report /home/dac/ClionProjects/openshell/CMakeFiles 2
[ 28%] [FLEX][openshell] Building scanner with flex 2.5.39
/usr/bin/flex -oshellparser.c shellscanner.l
cd /home/dac/ClionProjects/openshell && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell /home/dac/ClionProjects/openshell/CMakeFiles/openshell.dir/DependInfo.cmake --color=
Scanning dependencies of target openshell
make[2]: Leaving directory '/home/dac/ClionProjects/openshell'
make -f CMakeFiles/openshell.dir/build.make CMakeFiles/openshell.dir/build
make[2]: Entering directory '/home/dac/ClionProjects/openshell'
/usr/bin/cmake -E cmake_progress_report /home/dac/ClionProjects/openshell/CMakeFiles 3
[ 42%] Building C object CMakeFiles/openshell.dir/shellparser.c.o
/usr/bin/cc   -Wall -Werror -O3 -std=c99 -I/usr/include/readline    -o CMakeFiles/openshell.dir/shellparser.c.o   -c /home/dac/ClionProjects/openshell/shellparser.c
shellparser.c: In function ‘yy_init_buffer’:
shellparser.c:1432:48: error: implicit declaration of function ‘fileno’ [-Werror=implicit-function-declaration]
         b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
                                                ^
shellscanner.l: At top level:
shellparser.c:1181:17: error: ‘yyunput’ defined but not used [-Werror=unused-function]
     static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
                 ^
shellparser.c:1223:16: error: ‘input’ defined but not used [-Werror=unused-function]
     static int input  (yyscan_t yyscanner)
                ^
cc1: all warnings being treated as errors
CMakeFiles/openshell.dir/build.make:62: recipe for target 'CMakeFiles/openshell.dir/shellparser.c.o' failed
make[2]: *** [CMakeFiles/openshell.dir/shellparser.c.o] Error 1
make[2]: Leaving directory '/home/dac/ClionProjects/openshell'
CMakeFiles/Makefile2:98: recipe for target 'CMakeFiles/openshell.dir/all' failed
make[1]: *** [CMakeFiles/openshell.dir/all] Error 2
make[1]: Leaving directory '/home/dac/ClionProjects/openshell'
Makefile:78: recipe for target 'all' failed
make: *** [all] Error 2

我的构建文件是

cmake_minimum_required(VERSION 3.0)

project(openshell)
find_package(FLEX)

FLEX_TARGET(openshell shellscanner.l shellparser.c)


add_executable(openshell shellparser.c ${FLEX_ShellScanner_OUTPUTS} main.c openshell.h errors.c errors.h util.c util.h stack.c stack.h shellscanner.l shellscanner.h)


set(CMAKE_VERBOSE_MAKEFILE on)
include_directories(/usr/include/readline)

#### Lemon bootstrap ####
ADD_EXECUTABLE(lemon lemon.c)

file(GLOB SOURCES "./*.c")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -O3 -std=c99")

target_link_libraries(openshell ${READLINE_LIBRARY} ${FLEX_LIBRARIES})

我必须更改编译器选项吗?我的文件结构是:

$ tree
.
├── CMakeCache.txt
├── CMakeFiles
│   ├── 3.2.2
│   │   ├── CMakeCCompiler.cmake
│   │   ├── CMakeCXXCompiler.cmake
│   │   ├── CMakeDetermineCompilerABI_C.bin
│   │   ├── CMakeDetermineCompilerABI_CXX.bin
│   │   ├── CMakeSystem.cmake
│   │   ├── CompilerIdC
│   │   │   ├── a.out
│   │   │   └── CMakeCCompilerId.c
│   │   └── CompilerIdCXX
│   │       ├── a.out
│   │       └── CMakeCXXCompilerId.cpp
│   ├── cmake.check_cache
│   ├── CMakeDirectoryInformation.cmake
│   ├── CMakeOutput.log
│   ├── CMakeRuleHashes.txt
│   ├── CMakeTmp
│   ├── feature_tests.bin
│   ├── feature_tests.c
│   ├── feature_tests.cxx
│   ├── lemon.dir
│   │   ├── build.make
│   │   ├── C.includecache
│   │   ├── cmake_clean.cmake
│   │   ├── DependInfo.cmake
│   │   ├── depend.internal
│   │   ├── depend.make
│   │   ├── flags.make
│   │   ├── lemon.c.o
│   │   ├── link.txt
│   │   └── progress.make
│   ├── Makefile2
│   ├── Makefile.cmake
│   ├── openshell.dir
│   │   ├── build.make
│   │   ├── C.includecache
│   │   ├── cmake_clean.cmake
│   │   ├── DependInfo.cmake
│   │   ├── depend.internal
│   │   ├── depend.make
│   │   ├── flags.make
│   │   ├── flex
│   │   │   ├── lemon.c.o
│   │   │   └── shellparser.c.o
│   │   ├── lemon.c.o
│   │   ├── link.txt
│   │   ├── progress.make
│   │   ├── stack.c.o
│   │   └── util.c.o
│   ├── parser.dir
│   │   ├── build.make
│   │   ├── cmake_clean.cmake
│   │   ├── DependInfo.cmake
│   │   ├── depend.internal
│   │   ├── depend.make
│   │   └── progress.make
│   ├── Progress
│   │   ├── 1
│   │   ├── 2
│   │   ├── 3
│   │   └── count.txt
│   ├── progress.marks
│   └── TargetDirectories.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── digenv.c
├── errors.c
├── errors.h
├── example.c
├── example.h
├── flex
│   ├── digenv.c
│   ├── errors.c
│   ├── errors.h
│   ├── example.c
│   ├── example.h
│   ├── lemon
│   ├── lemon.c
│   ├── lempar.c
│   ├── lex.yy.c
│   ├── main.c
│   ├── main.c~
│   ├── main.h
│   ├── main.o
│   ├── Makefile
│   ├── Makefile~
│   ├── miniShell2.c
│   ├── openshell
│   ├── openshell.c
│   ├── openshell.h
│   ├── openshell.l
│   ├── pipeline.c
│   ├── README.md
│   ├── shell
│   ├── shellparser.c
│   ├── shellparser.h
│   ├── shellparser.hpp
│   ├── shellparser.o
│   ├── shellparser.out
│   ├── shellparser.y
│   ├── shellparser.y~
│   ├── shellscanner.h
│   ├── shellscanner.l
│   ├── shellscanner.o
│   ├── snazzle
│   ├── util.c
│   └── util.h
├── lemon
├── lemon.c
├── lempar.c
├── lex.yy.c
├── main.c
├── main.h
├── main.o
├── Makefile
├── miniShell2.c
├── openshell
├── openshell.c
├── openshell.h
├── pipeline.c
├── README.md
├── shellparser.c
├── shellparser.h
├── shellparser.hpp
├── shellparser.o
├── shellparser.out
├── shellparser.y
├── shellscanner.h
├── shellscanner.l
├── shellscanner.o
├── snazzle
├── snazzle.l~
├── stack.c
├── stack.h
├── util.c
└── util.h

11 directories, 127 files
dac@dac-Latitude-E7450:~/ClionProjects/openshell$ 

我的 flex 语法是

%include {
#include <stdio.h>
#include <assert.h>
}

%token_type {const char*}

%syntax_error
{
    fprintf(stderr, "Error parsing command\n");
}

start ::= in .
in ::= .
in ::= in commandList EOL .
{
    printf("in ::= in commandList EOL .\n");
    printf("> ");
}

commandList ::= command PIPE commandList .
{
    printf("commandList ::= command PIPE commandList .\n");
}
commandList ::= command .
{
    printf("commandList ::= command .\n");
}

command ::= FILENAME argumentList .
{
    printf("command ::= FILENAME argumentList .\n");
}
command ::= FILENAME .
{
    printf("command ::= FILENAME .\n");
}

argumentList ::= argument argumentList .
{
    printf("argumentList ::= argument argumentList .\n");
}
argumentList ::= argument .
{
    printf("argumentList ::= argument .\n");
}
argument ::= ARGUMENT .
{
    printf("argument ::= ARGUMENT .\n");
}
argument ::= FILENAME .
{
    printf("argument ::= FILENAME .\n");
}

使用编译器标志 -Werror 所有警告都被视为错误。 您必须删除此标志,编译将无错误地完成。

编译器标志中 -Wall-Werror 的组合对于 flex 生成的代码来说过于严格。您可以通过添加更多选项告诉编译器将特定错误视为常规警告:

-Wno-error=implicit-function-declaration
-Wno-error=unused-function

基本上只是将 no- 插入到编译器打印的 -Werror= 诊断中。

最佳做法是只将这些编译器选项添加到 flex 生成的特定源文件,而不是整个项目。在您的情况下,它可能看起来像这样:

set_source_files_properties(shellparser.c PROPERTIES COMPILE_FLAGS
    -Wno-error=implicit-function-declaration
    -Wno-error=unused-function
)

或者如果您想完全避免此文件的警告,这可能是个好主意,这样您就不会习惯于容忍警告:

set_source_files_properties(shellparser.c PROPERTIES COMPILE_FLAGS
    -Wno-implicit-function-declaration
    -Wno-unused-function
)

最后,您实际上可以通过在 flex 语法文件的顶部添加以下代码来解决未声明的 fileno 问题:

%{
#include <stdio.h>
%}