3
votes

I'm using Bison and Flex in an Xcode project. I didn't want to put the generated files under source control, so I was happy to find that Xcode natively supports Bison/Flex files, generating the parsers on-the-fly in its derived data folder. So far so good.

However, Xcode uses an embedded old Bison version (2.3):

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/yacc

which doesn't yet support the %define api.pure full directive. Since this bison executable is under the Xcode.app bundle I can't replace it, so I installed the latest version via Brew and added it to my $PATH through ~/.bash_profile (~/.bashrc also sources my bash profile). So in bash I can say:

$ which bison
/usr/local/Cellar/bison/3.0.4/bin//bison

However, Xcode still uses it's own version... I suppose the path to the internal bison is hardcoded.

My second approach was to create a custom build rule for Yacc files, and run the correct version of bison from there. This time the problem was that as Xcode ran my custom build rule, it immediately tried to build the resulting C files. The generated C files would however depend on the header file yet to be generated by Flex, because that's where e.g. yyscan_t is declared (used by Bison in the generated C file). But on the other hand, Flex-generated C files also include the Bison-generated header, so compiling with Flex first doesn't help...

What I need is to first only generate the Flex and Bison headers/sources and then build them along with the rest of the project.

How can I achieve this?

4
Cant you just edit the Build Rule?rici

4 Answers

2
votes

I've managed to solve the issue by putting the *.l and *.y files under a *.parser folder and adding that folder to the project. Then I removed the *.l and *.y files added the folder to the compiled sources:

compile sources phase

And then made a Build Rule for *.parser like this:

build rule for *.parser

This enables me to first run yacc and lex and only then will the resulting *.cpp files be passed to the compilation step.

1
votes

If you go to your build target, Build Phases, and click the + on the bar with the search box on it, you can add a New Run Script Phase. You can then drag that above your current Compile Sources phase. You can do whatever you want in that script phase, and it will run before compilation starts.

Xcode build target

0
votes

I've managed to do it with custom build rules, using bison installed from brew and flex that comes with macOS, not the one bundled with Xcode. I'm not sure if my problem was the same as yours, but if you want to take a look my project is on GitHub.

0
votes

This is a bit of a Zombie, but if I ever come back here again, I will want to see the answer.

Certainly from XCode 12 (probably before) the answer is trivially easy.

(1) Go to build settings (2a) Press the + for a brand new setting variable. (2b) Change the NAME to YACC, and it's VALUE to /usr/local/bin/bison (or whatever path you need for brew).

(3a) Press the + for a brand new setting variable. (3b) Change the NAME to LEX, and it's VALUE to /usr/local/bin/flex (or whatever path you need for brew).

(4+) use the YACC/LEX settings for flags that you want to use.

Build Settings