Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trouble compiling a *.l file using CMake #69

Open
anphetamina opened this issue Dec 3, 2020 · 7 comments
Open

Trouble compiling a *.l file using CMake #69

anphetamina opened this issue Dec 3, 2020 · 7 comments

Comments

@anphetamina
Copy link

anphetamina commented Dec 3, 2020

I'm trying to compile the provided c++ example from the doc:

%{
#include <iostream>
using namespace std;
int mylineno = 0;
%}

%option noyywrap c++

string  \"[^\n"]+\"

ws      [ \t]+

alpha   [A-Za-z]
dig     [0-9]
name    ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
num1    [-+]?{dig}+\.?([eE][-+]?{dig}+)?
num2    [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
number  {num1}|{num2}

%%

{ws}    /* skip blanks and tabs */

"/*"    {
        int c;

        while((c = yyinput()) != 0)
            {
            if(c == '\n')
                ++mylineno;

            else if(c == '*')
                {
                if((c = yyinput()) == '/')
                    break;
                else
                    unput(c);
                }
            }
        }

{number}  cout << "number " << YYText() << '\n';

\n        mylineno++;

{name}    cout << "name " << YYText() << '\n';

{string}  cout << "string " << YYText() << '\n';

%%

// This include is required if main() is an another source file.
//#include <FlexLexer.h>

int main( int /* argc */, char** /* argv */ )
{
    FlexLexer* lexer = new yyFlexLexer;
    while(lexer->yylex() != 0)
        ;
    return 0;
}

I've also put the path to the winflexbison folder in my PATH environment variable. Using this CMake file:


cmake_minimum_required(VERSION 3.17)
project(myproject)

set(CMAKE_CXX_STANDARD 11)

find_package(BISON)
find_package(FLEX)

FLEX_TARGET(lexer lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp)

add_executable(myproject main.cpp ${FLEX_lexer_OUTPUTS})

It will always say:

fatal error: FlexLexer.h: No such file or directory
 
          ^            
compilation terminated.

Inside the lexer.cpp file generated is not able to localize FlexLexer.h. Am I missing something?

@lexxmark
Copy link
Owner

lexxmark commented Dec 4, 2020

as I know FlexLexer.h is a mandatory file when you generate C++ lexer. It should be in the same folder where win_flex.exe resides.

It seems Cmake know it somehow and tries to locate it.

@anphetamina
Copy link
Author

Is this line necessary in the CMakeLists?
target_link_libraries(${project_name} ${FLEX_LIBRARIES})

@anphetamina
Copy link
Author

Adding the line I have mentioned above I always get this CMake error

CMake Error: The following variables are used in this project, but they are set to NOTFOUND. Please set them or make sure they are set and tested correctly in the CMake files: FL_LIBRARY (ADVANCED)

@lexxmark
Copy link
Owner

lexxmark commented Dec 7, 2020

I'm not experienced in CMake and thus cannot help here.

@LonghronShen
Copy link
Contributor

@anphetamina I think this PR #79 and the mentioned example might help

@GitMensch
Copy link
Collaborator

@LonghronShen So we do have a new version with the PR included (available binaries found in the README as CI artifacts) now. Can you please elaborate where the issue with the initial approach is?

@LonghronShen
Copy link
Contributor

LonghronShen commented Sep 9, 2021

Thank you for the quick merge!

The CMake code snip from the OP:

find_package(BISON)
find_package(FLEX)

The FindFlex and FindBison module bundled with the CMake itself assumes that the Flex and Bison installation is on the default search path. This is not a problem for working on non-Windows platforms, or a custom CMake toolchain is provided. But for Windows users, this is not very easy for CMake to automatically find WinFlexBison without proper installation or settings.

If you don't want to install the WinFlexBison by tools like chocolatey, or write a custom CMake toolchain that defines the search path for flex and bison, with the PR #79 and the CMake modules provided in the example, you can now directly import and add WinFlexBison as a pure CMake dependency like this:

include(FetchContent)

if(WIN32)
    # winflexbision
    FetchContent_Declare(winflexbision 
        GIT_REPOSITORY https://github.com/lexxmark/winflexbison.git
        GIT_TAG master)

    FetchContent_GetProperties(winflexbision)
    if(NOT winflexbision_POPULATED)
        FetchContent_Populate(winflexbision)
        add_subdirectory(${winflexbision_SOURCE_DIR} ${winflexbision_BINARY_DIR} EXCLUDE_FROM_ALL)

        execute_process(COMMAND ${CMAKE_COMMAND}
            -S ${winflexbision_SOURCE_DIR}
            -B ${CMAKE_BINARY_DIR}/external/winflexbision
            -G ${CMAKE_GENERATOR}
            -D CMAKE_BUILD_TYPE=Debug
            -D CMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
            -D CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG=${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}
            -D CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}
        )

        execute_process(COMMAND ${CMAKE_COMMAND}
            --build ${CMAKE_BINARY_DIR}/external/winflexbision
        )

        execute_process(COMMAND ${CMAKE_COMMAND}
            --install ${CMAKE_BINARY_DIR}/external/winflexbision --prefix ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
        )

        set(BISON_ROOT_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" CACHE STRING "BISON_ROOT_DIR" FORCE)
        set(FLEX_ROOT_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" CACHE STRING "FLEX_ROOT_DIR" FORCE)

        set(BISON_EXECUTABLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/win_bison.exe" CACHE STRING "BISON_EXECUTABLE" FORCE)
        set(BISON_version_result "0" CACHE STRING "BISON_version_result" FORCE)
        set(BISON_version_output "bison++ Version 1,0,0" CACHE STRING "BISON_version_result" FORCE)

        set(FLEX_EXECUTABLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/win_flex.exe" CACHE STRING "FLEX_EXECUTABLE" FORCE)
        set(FLEX_version_result "0" CACHE STRING "FLEX_version_result" FORCE)
        set(FLEX_FIND_REQUIRED "0" CACHE STRING "FLEX_FIND_REQUIRED" FORCE)

        include(UseBISON)
        include(UseFLEX)
    endif()

    # unistd_h
    FetchContent_Declare(unistd_h
        GIT_REPOSITORY https://github.com/win32ports/unistd_h.git
        GIT_TAG 0dfc48c1bc67fa27b02478eefe0443b8d2750cc2)

    FetchContent_GetProperties(unistd_h)
    if(NOT unistd_h_POPULATED)
        FetchContent_Populate(unistd_h)
        # add_subdirectory(${unistd_h_SOURCE_DIR} ${unistd_h_BINARY_DIR} EXCLUDE_FROM_ALL)
        include_directories(${unistd_h_SOURCE_DIR})
    endif()
else()
    if(APPLE)
        find_program(MAC_HBREW_BIN brew)

        if(MAC_HBREW_BIN)
            execute_process(COMMAND ${MAC_HBREW_BIN} "--prefix" OUTPUT_VARIABLE BREW_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
            list(INSERT CMAKE_PREFIX_PATH 0 ${BREW_PREFIX})
        endif()

        execute_process(
            COMMAND ${MAC_HBREW_BIN} --prefix bison
            RESULT_VARIABLE BREW_BISON
            OUTPUT_VARIABLE BREW_BISON_PREFIX
            OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        if(BREW_BISON EQUAL 0 AND EXISTS "${BREW_BISON_PREFIX}")
            message(STATUS "Found Bison keg installed by Homebrew at ${BREW_BISON_PREFIX}")
            set(BISON_EXECUTABLE "${BREW_BISON_PREFIX}/bin/bison")
            list(INSERT CMAKE_PREFIX_PATH 0 "${BREW_BISON_PREFIX}")
        else()
            message(FATAL_ERROR "Cannot find bison from homebrew.")
        endif()

        execute_process(
            COMMAND ${MAC_HBREW_BIN} --prefix flex
            RESULT_VARIABLE BREW_FLEX
            OUTPUT_VARIABLE BREW_FLEX_PREFIX
            OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        if(BREW_FLEX EQUAL 0 AND EXISTS "${BREW_FLEX_PREFIX}")
            message(STATUS "Found Flex keg installed by Homebrew at ${BREW_FLEX_PREFIX}")
            set(FLEX_EXECUTABLE "${BREW_FLEX_PREFIX}/bin/flex")
            list(INSERT CMAKE_PREFIX_PATH 0 "${BREW_FLEX_PREFIX}")
        else()
            message(FATAL_ERROR "Cannot find flex from homebrew.")
        endif()
    endif()

    find_package(BISON REQUIRED)
    find_package(FLEX REQUIRED)
endif()

...

BISON_TARGET(xy_parser syntactic.y ${CMAKE_CURRENT_BINARY_DIR}/syntactic.cpp)
FLEX_TARGET(xy_scanner lexical.l  ${CMAKE_CURRENT_BINARY_DIR}/lexical.cpp)
ADD_FLEX_BISON_DEPENDENCY(xy_scanner xy_parser)

add_library(xy-compiler-parser STATIC
    ${SRC}
    ${BISON_xy_parser_OUTPUTS}
    ${FLEX_xy_scanner_OUTPUTS})

target_link_libraries(xy-compiler-parser 
    PUBLIC ${llvm_libs}
    PUBLIC ${FLEX_LIBRARIES})

target_include_directories(xy-compiler-parser
    PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
    PUBLIC ${CMAKE_CURRENT_LIST_DIR})

if(WIN32)
    add_dependencies(xy-compiler-parser
        win_bison
        win_flex)
endif()

Note:

  • target_link_libraries is important because this will automatically add the include directory of flex into the include directories list of this target so that FlexLexer.h can be found when compiling this target.
  • The trick is that an external CMake based project repo can be added as an dependency using the FetchContent module. So the whole WinFlexBison project is included, and the Unistd patch is also included. After the project is fetched, the build and installation command can be called so that the WinFlex and WinBison can be installed into the output directory of the current project. Then the bison and flex executable and header file paths can be inferred and directly injected to override the default actions in the FindFlex and FindBison module bundled with the CMake.
  • The modification in the PR [cmake] Improve support using CMake #79 contains the libfl and liby which are required by some projects, so that ${FLEX_LIBRARIES} will work as expected.
  • By the way, the PR [cmake] Improve support using CMake #79 only applies to the 3.x branch. For the 2.x branch, you can use the 2.x branch of my fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants