cmakefilecmakeflex-lexerlemon

build error using flex-lexer and cmake


i'm learning cmake and flex-lexer but i get a build problem with error code 2 according to the error message from make:

$ 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

My build file is

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})

Is it the compiler options that I must change? My file structure is:

$ 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$ 

My flex grammar is

%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");
}

Solution

  • The combination of -Wall and -Werror in your compiler flags is too strict for the code generated by flex. You can tell the compiler to treat the specific errors as regular warnings by adding a couple more options:

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

    Basically just inserting no- into the -Werror= diagnostics the compiler printed.

    Best practice would be to only add these compiler options to the specific source files generated by flex, not your entire project. In your case it might look like this:

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

    Or if you want to avoid the warnings entirely for this file, which might be a good idea so you don't grow accustomed to tolerating warnings:

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

    Finally, you may actually be able to fix the undeclared fileno issue by adding this at the top of your flex grammar file:

    %{
    #include <stdio.h>
    %}