Last time I wrote about using Flex in C++ mode, the sample code was targeted at the Linux environment; a simple makefile was used for compilation, and flex / bison were assumed to be in $PATH. Some interest was shown – both by myself and others – in getting flex running in Visual C++. This turned out to take a little bit more work than I had thought, so I am creating this post to outline the steps that need followed.
First off, there is a port of Flex to Win32. That port, however, is several years old (2004). Don’t let the version number fool you; despite the Win32 port being version 2.5.4a, the latest official Flex release is 2.5.35, which is much newer. A lot of work has gone into the C++ skeleton in that time, so I obviously was interested in using the latest version. Porting 2.5.35 to Win32 would have been the ideal solution, but I have neither the time nor the inclination – especially since there is a viable workaround in Cywin.
For those of you unfamiliar with Cygwin, it is a ‘Linux API layer providing substantial Linux API functionality’. Long story short, it will allow us to use the official Flex release without modification on Windows. Download the setup program and use it to install Cygwin. When asked to choose additional packages, make sure to search for and select Flex. You only need the binaries, not the source. When you are done installing, you can go to Start -> Cygwin -> Cygwin Bash Shell and run ‘flex –version’; you should see ‘flex 2.5.35′ as the result.
If you don’t mind invoking flex from the command line every time you change your flex source file, skip this paragraph. If you want the Visual Studio IDE to call Flex for you, check out this MSDN article on custom build rules. Download the example and install it (I know, an installer is overkill). Since the example was made in an old version of Visual Studio, you have to open the solution so it can convert the .rules file they provided to a new .targets file (VS 2010). After you have converted the solution, you can include the .targets file in your Flex solution. Right-click on the project and select Build Customizations…. Choose Find Existing and browse to where you extracted the MSDN example; choose FlexBison.targets. Make sure FlexBison is checked back in the Build Customizations window
Add your .l file to the project, right-click on it and select Properties. Exclude from Build should be No, and Item Type should be Flex Generator. You can control the command-line arguments sent to flex using the Flex Generator node on the left pane. Now you have to tell VS where flex.exe is; right-click on your project and choose Properties. Under VC++ Directories edit the Executable Directories to include your Cygwin bin path; For example, mine reads ‘$(ExecutablePath);D:\Cygwin\bin’. Cygwin build path MUST come after the default paths or Visual Studio will use some of the executables in that directory instead of its own, and will not be able to build the solution.
After you run the Flex generator, include the generated CPP file in your project. The Flex C++ skeleton references the file FlexLexer.h, so you need to add this file somewhere in your project’s include directories. I put the entire Cygwin include (INSTALL_DIR\usr\include) at the END of my project include directories; putting it before $(IncludePath) WILL break your build, since VC++ will use cygwin headers instead of the MSVC headers.
One final note: you must ‘#define YY_NO_UNISTD_H’ in your scanner header file that you have to write before you include FlexLexer.h; Windows does not have unistd.h. For a complete example of a (trivial) flex project in Visual C++ 2010, you can download my example here
- Install Cygwin and the Flex package
- Download the Visual C++ Custom Build Rules example
- Open the VC++ example to convert the .rules file to a .targets file
- Create a new C++ project and add a Flex source file
- Add .targets file to project Available Build Customization Files
- Add Cygwin bin path to the end of your project executable directories
- Add Cygwin include path to the end of your project include directories