Sublime Forum

Building with Make, Regex and F4

#21

As a ridiculously simple test;

test.c


#include <stdio.h>

int main (int argc, char **argv)
{
    printf("Hello, World!\n")
    return 0;
}

Makefile


all: test
	./test

test: test.o
	clang -o test test.o

test.o: test.c
	clang -c test.c

Lozminda.sublime-build


{
  "shell_cmd" : "make",
  "selector" : "source.c",

  "file_regex":"^(|..[^:]*):([0-9]*):?([0-9]*)?:? (.*)$",
  "working_dir": "${folder:${project_path:${file_path}}}",
  "syntax": "Packages/Makefile/Make Output.sublime-syntax"
}

The folder structure has the Makefile and test.c sitting in the same folder; executing the build with the build you have here produces this output:

clang -c test.c
clang -o test test.o
./test
Hello, World!
[Finished in 0.1s]

All as we would expect. Now, remove the semicolon on the printf and build again:

lang -c test.c
test.c:5:30: error: expected ';' after expression
    printf("Hello, World!\n")
                             ^
                             ;
1 error generated.
make: *** [Makefile:8: test.o] Error 1
[Finished in 0.0s with exit code 2]
[shell_cmd: make]
[dir: /tmp/bob/test]
[path: ... ]

An error is detected by clang, which reports it. Also because make returns a failure, Sublime displays a diagnostic that tells you what command it executed, what directory was the current directory, and the path at the time (which I have clipped just because my path is excessively long).

Seems like things work on the face of it, based on the output.

The file_regex is what tells Sublime that a line contains a result to be navigated. Yours looks like this:

^(|..[^:]*):([0-9]*):?([0-9]*)?:? (.*)$

The first capture group is the name of the file:

(|..[^:]*):

So, the filename is either any two characters (..), followed by 0 or more characters that aren’t a colon ([^:]*), followed by a :. OR, due to the alternation operator, the filename can be nothing at all.

Then, there’s this output:

[dir:

So, [ matches the first ., and d matches the second ., and then ir matches [^:]*, the next character is : which closes off the capture group, and what was captured was [dir as a filename.

What you expect? No. What you told it was acceptable? yep.

Your regex looks like it’s based on the one from C Single File.sublime-build (or one of my examples perhaps, which come from there), except that the filename field has the alternation in it.

That one is meant to parse gcc output, but clang produces different output than gcc does. I’d try something like this:

  "file_regex":"^(..[^:]*):([0-9]*):([0-9]*): (.*)$",

Similar to the one you’re using, but the row and column for the error are now not optional (and the filename isn’t allowed to be empty), which should match a bit better based on my sample of this case right here.

0 Likes

#22

I’ll give it a go, just to say the regex I’m using works on clang fine, it’s when error come via clang via a makefile that I’m having trouble…

Also if I build with the same makefile using a different compiler option (g++) F4 works.
If just compile with clang++ (no makefile) F4 works
If i use a makefile which compiles with clang F4 doesn’t work

Same results as above with new regex…

0 Likes

#23

Up to here I’ve done everything you say, test.c and make as you descrided in the same folder. When I hit build

make: *** No targets. Stop.

Maybe this is a clue ?

0 Likes

#24

Worked when I did it; you may want to make sure that your paste is using tabs for the rules; some versions of make get cranky about space indented rules and this is the message you see when that happens.

0 Likes

#25

Yep checKed them

tried cmd “make all”. The error is make: *** No rule to make target `all’. Stop.

Bizarely I get an error banner in my make file.
bizzare%20error%20banner

I’ll try again with out make all…

No joy. Here’s a screen shot of both make and test.c in the same dir
same%20dirs

0 Likes

#26

Have done some jiggling of my own, we have landed, there’s an error F4 works…

  "shell_cmd" : "make --file=make.mk",
  "selector" : "source.c",

  "file_regex":"^(|..[^:]*):([0-9]*):?([0-9]*)?:? (.*)$",
  "working_dir": "${folder:${project_path:${file_path}}}",
  "syntax": "Packages/Makefile/Make Output.sublime-syntax"

and obvs changed the name of the make file to make.mk…

It seems to be when clang runs through make it’s initial output before it gets to the errors is slightly larger than when it’s not running through make…

What does this text highlighting signify (in the commandline ouptut panel) ?
highlighed

Everything but the last three lines is highlighted. The highlighting is different depending on make and compiler options…

0 Likes

How is this Highlighting generated by ST3 and why
#27

Can I ask why you keep making the capture for the filename include an empty capture? Are you trying to capture lines that start with :line:col or something?

0 Likes

#28

Morning/Evening. When you say capture, I’m assuming you’re talking about the regex ? I’m not trying to capture anything. The regex’s that I’ve used are only the ones (I think it’s just you) have suggested.
I don’t know anything about regex. Why I keep sending you a screenshot is that the highlighted pattern of text is different depending on what build system (make,g++,clang++ or combinations) i use (even though the regex is the same except for the different ones you suggested in this post) thus if I/we knew what the purpose of the highlighted text was (because I’m not highlighting it ST3 is) it might give us some clue as to what was going on…? (Or not, I have no idea how ST3 works, again I could take stab, but that’s it)
So far our diagnostic tools aren’t working I thought maybe look at some edge cases. Now I could be barking up the wrong tree completely, which was why I wanted to know what the text highlighting is in the “error box” (sorry don’t know correct name for it couldn’t find it).
If this is pointless so be it. What is the text highlighting showing ?

Ta

0 Likes

#29

The file_regex is used to match lines that have error/message output, and in order to do so it has to capture the information out of the line. In particular, at a minimum it needs to capture the name of the file, or it can’t open it. Then, if it also captures a line, it can open the file and go to the correct line. If it also captures a column number, it can focus on the error directly, and if it ALSO captures the message text, it can display it to you.

What a regex is and how they work is out of scope for the conversation here, but the parts of the regex wrapped in () are the captures; they tell the regex engine to store the text that was matched for use later.

One of the constructs in a regex is the | which means “or”. So for example, a regex of this|that will match either the word this OR the word that. In your regex above, you have (|..[^:]*): which is meant to match the filename. However it starts with a | which means “match anything, OR whatever this second match is”. Unsurprisingly, when given the choice to match nothing, there’s a lot of places in the file to choose from that satisfy that.

I’m pretty sure that regex didn’t come from me (if it did please trace where I said it so that it can be fixed). As I mentioned above, that’s almost certainly not a regex that’s going to work for you for clang (it matches incorrectly here even in the simple test I outlined above), while the fixed regex I provided works for clang just fine.

0 Likes

#31

Re reading that post it looks like I might hve got it from one of your vids…
BTW the regex with the ‘|’ has worked for the last 18 months, it’s only since using make to build files has that regex stopped working (and agin it does work with make and g++). TBH I don’t think it’s the regex as I’ve replaced the old regex, with the one you’ve suggested…

Cheers

0 Likes

#32

If I put a broken regex in one of my videos I’d love to know about it; if you happen to run across it, please let me know. If I had any regex related to this in a video, it should have been copied directly from the C Single File.sublime-build file, which does not look like that.

0 Likes

#33

Right. (he says business like) we’re getting somewhere.

Firstly and least importantly the verbose flag ‘-v’ wrecks the file_regex, which although not directly stated in the documentation it says it can only process four lines ? (I put that in italics because I’m not certain.)

Now to the meat. After some fiddling the problem Is (85% certain) the regex. The regex that isn’t commented out nearly works and is an ammalgamation of one of the regex’s from the post below:

and what I’ve already got…

{
  "cmd" : ["make default --file=build_MUTAG_Dbug.mk -B TARGET=\"$file_base_name\""],
  "selector" : "source.c", 
  "shell": true,

  // "file_regex":"^(..[^:]*):([0-9]*):([0-9]*): (.*)$",
  // "file_regex":"^(|..[^:]*):([0-9]*):([0-9]*): (.*)$",

  // "file_regex": "^(.+):([0-9]+)()?: error: (.*)$",

  "file_regex": "^(.+):([0-9]*):([0-9]+)()?: error: (.*)$",

  "working_dir": "${folder:${project_path:${file_path}}}",

  // "working_dir": "${file_path}",
  // "working_dir": "/home/elitebook/Desktop/Big Mandlebrot/Final Project/",

  "syntax": "Packages/Makefile/Make Output.sublime-syntax",

This regex

"file_regex": "^(.+):([0-9]*):([0-9]+)()?: error: (.*)$",

on pressing of F4 takes the cursor to the error (and this is the best functionality I’ve had so far in the makefile caper) however the red banner doesn’t display any information. See screen shot below:

The error is at line 216, and cursor unfortunately disappears when I take the screen shot, but it is there at the right place.

If we could improve the regex so I get the error message in the banner (the red error box that here is just a square with a cross in it) that’s be a win. Otherwise it’s at least almost working :crazy_face:

Thanks for your perseverence, to @OdatNurd especially.

Happy Monday !

:unicorn::skull_and_crossbones:

0 Likes

#34

Warning: This might not be a very useful post, apologies in advance

OdatNurd

Feb 2017

How are the regex captures separated in the regex?

Regex captures are represented by the pairs of ( and ) ; instead of matching actual text, they tell the regex engine that whatever text is matched at those locations should be saved for future use.

In the Replace panel, the captures can be used in the replacement text with codes like \1 for the first capture, \2 for the second, and so on. Here sublime is using internally to determine exactly what file, line and column errors are happening at.

I have put an error output from a build into a file, and have been trying to run this regex on it in a search, and I am not getting any match.

The regex as you have it above is not correct; it’s missing some * characters. Are you sure that’s the one that you’re using in your build system? It is almost but not quite identical to the one that’s used by default in Sublime for C/C++ build output.

For comparison:

Yours:   ^(..[^:]):([0-9]+):?([0-9]+)?:? (.)$
Default: ^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$

I guess we’re just talking about the first ’ | ’ As you can see that regex has been kicking around for sometime… Maybe I copied it off SO. I do remember watching one of your vids, but it was a year ago. I have certainly ‘misquoted’ the wrong formula but the wrong formula does work (and has been working for the last year) just not in make files.
Apologies if I’ve misquoted you.
Cheers
L

0 Likes

#35

In case anyone else is struggling I finally got it to work, it was down to the regex and not any of the directory shenaneghans. Here’s a bit of my build file

{
      "cmd" : ["make default --file=build_MUTAG_Dbug.mk -B TARGET=\"$file_base_name\""],
      "selector" : "source.c", 
      "shell": true,
      "file_regex": "^(.+):([0-9]*):([0-9]*):(.*)$",
      "working_dir": "${file_path}",
      "syntax": "Packages/Makefile/Make Output.sublime-syntax",
      "variants":
      [

And here’s the regex. This works with clang++ and g++ from make, with full F4 functionality…

"file_regex": "^(.+):([0-9]*):([0-9]*):(.*)$",

0 Likes