Sublime Forum

Build system can't resolve relative paths

#1

I’m trying to use a Makefile build system but navigating to errors is not working properly. The problem seems to be that the file paths are relative so ST doesn’t know where to find them. If I double-click them a new tab is opened with no text even though the file clearly exists in the project.

Can I make ST navigate to the correct file or do I need to force “make” to produce absolute paths? I’d also be curious to know about the “working_dir” value as I’m not sure what that resolves to.

Here’s an example of the an error:

…/lib/Syndicate/Data/SpriteData.h:34:156: warning: instantiation of variable ‘Syndicate::Data::Colors::_default’ required here, but no definition is available [-Wundefined-var-template]

Here’s the build system (which comes with ST I think):

{
  "shell_cmd": "make",
  "file_regex": "^(..[^:\n]*):([0-9]+):?([0-9]+)?:? (.*)$",
  "working_dir": "${folder:${project_path:${file_path}}}",
  "selector": "source.makefile",
  "syntax": "Packages/Makefile/Make Output.sublime-syntax",
  "keyfiles": ["Makefile", "makefile"],
  "variants":
  [
    {
      "name": "Clean",
      "shell_cmd": "make clean"
    }
  ]
}
0 Likes

#2

Depending on what your Makefile is doing when it’s running, modifying the working_dir may do what you want here.

If you peek into Default/exec.py using View Package File from the command palette and look near the start of the ExecCommand class, these lines exist:

        self.output_view.settings().set("result_file_regex", file_regex)
        self.output_view.settings().set("result_line_regex", line_regex)
        self.output_view.settings().set("result_base_dir", working_dir)

These settings are what controls how results are grabbed from the build output; file_regex and line_regex are used (as documented in build systems) to capture the name of the file that has the error and the location inside of it, and base_dir is the location that relative filenames are relative to.

Thus the key here for you is that either the filenames that are generated in the build output need to be absolute so that they’ll always be files that exist, or working_dir needs to be set such that paths relative to it will be interpreted correctly. When that’s not the case you end up with Sublime opening tabs that are empty, as you’ve seen.

If you’re doing something where there’s a single Makefile somewhere in the project and it just executes rules, then you should be able to adjust working_dir so that it generates relative files properly. On the other hand if your Makefile does things like recursively call make to build inside of subdirectories, then this doesn’t work because the filenames generated are relative to the wrong place because make changes the current directory in that case.

The general format of variables in build systems (not just working_dir) is ${variable:default_value}, where if the variable isn’t set, the expanded value is default_value instead. In the case of working_dir in the example, the overall value should be the (first) folder open in the sidebar, but if there isn’t one then the location of the current sublime-project file is uses instead, and if you also don’t have a project open the fall back is the location where the current file is sitting.

0 Likes

#3

That’s more complicated than I thought and I don’t have much experience with make/gcc.

I think my best plan is to do make in the directory of the active file. There is a $file variable and $file_base_name but I don’t see a $file_dir or something similar which is the directory of the active file. Does that exist? If it does I can “cd” to that directory and call make there.

I’m thinking something like this would work because there is a make rule which has the same name as the file.

{
      "name": "Single File",
      "shell_cmd": "cd $file_dir; make $file_base_name"
}
0 Likes

#4

Basically the above advice distills down to something like if the Makefile exists inside of the top level folder, the default should be working for you out of the box. If make says something like Entering directory during the build, that’s an indication that it’s fiddling around with the current directory. Similarly commands that make is executing might do something similar on a temporary basis (which may be less obvious) which would also cause problems.

Ultimately without knowing what the contents of the Makefile are and the overall structure of the file, it’s hard to say what might be going wrong.

For your purposes here, the variable that you want is $file_path, which is the path to the folder that contains the currently active file. However for this build to work there would have to be a Makefile inside of the folder where the current file is stored, or make won’t know what to do.

You can also shorten that up to something like the following (plus whatever other keys you need):

{
    "working_dir": "$file_path",
    "shell_cmd": "make $file_base_name"
}

The working_dir tells Sublime to make sure that the current directory is the folder that the current file is stored in, so that’s what make will see as the current directory when it executes.

0 Likes

#5

Thanks, that command did work. I guess people who know makefiles good know to make a project in the correct folder so that the default build systems work. I think my problem was just dropping the directory in ST and building from there.

0 Likes