Skip to content

Conversation

@elliottt
Copy link
Contributor

@elliottt elliottt commented May 31, 2022

Add a new compile_commands.json target in c-dependencies/js-compute-runtime/Makefile for generating the build config that clangd requires. Typing make compile_commands.json will generate the file, and enable the use of clangd when working on js-compute-runtime.

Also make some small changes to the Makefile:

  • Replace uses of = with := when possible to avoid accidentally introducing macros
  • Add clean and distclean targets
  • Add entries for generated intermediates to .gitignore

@elliottt elliottt force-pushed the trevor/compile_commands.json branch from 1abdba2 to cd2bf50 Compare May 31, 2022 17:58
@elliottt elliottt marked this pull request as ready for review May 31, 2022 18:22
@elliottt elliottt requested a review from tschneidereit May 31, 2022 18:25
Copy link
Contributor

@jameysharp jameysharp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of good improvements here! I'm not immediately convinced that the changes to WASM_STRIP are correct, but all my other notes are quibbles you can feel free to ignore.

.gitignore Outdated
c-dependencies/js-compute-runtime/compiler_flags
c-dependencies/js-compute-runtime/*.o
c-dependencies/js-compute-runtime/*.d
c-dependencies/js-compute-runtime/*.wasm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious how you feel about placing these gitignore entries in c-dependencies/js-compute-runtime/.gitignore instead. It's mostly a question of style/personal preference and I don't feel strongly about it. But I personally tend to like keeping ignore rules closer to the part of the source tree that generates the files to be ignored. For me the main exception is when there are multiple subtrees that need to ignore the same things; I might put things like *.o at top-level if there are multiple separate C projects in-tree.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that too, but have seen preferences elsewhere for one global .gitignore. Why don't we move these into c-dependencies/js-compute-runtime/.gitignore and we can migrate rules like *.o out if we start accumulating more c++ source outside of that tree?

Q :=
else
MODE=release
CARGO_FLAG=--release
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If MODE and CARGO_FLAG are assigned with := above, should they be assigned that way here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, they definitely should be :)

$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) $(LD_FLAGS) -o $@ $^
$(WASM_STRIP)
$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) $(LD_FLAGS) -o $@ $^ && \
$(call WASM_STRIP,$@)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't touched makefiles in a while, but the GNU make manual says execution within a rule stops at the first line that exits with a non-zero status. So combining two lines with && is unnecessary and I think makes maintenance a little harder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This avoids the overhead of invoking the shell once per line, but that's probably not really something worth worrying about here. I'll switch it back because I agree that it's more readable on a separate line 👍

There is the .ONESHELL directive, but that brings back the opportunity for a command to fail and not halt rule execution.

ifeq (,$(findstring g,$(CXX_OPT)))
ifneq (,$(shell which wasm-opt))
WASM_STRIP = wasm-opt --strip-debug -o $@ $@
WASM_STRIP = wasm-opt --strip-debug -o $1 $1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does $1 work here? I see you've changed the usage of this variable to a $(call), but given that my reading of the GNU make manual (call function, variable references) is that you'd need to use $(1) rather than $1 here.

I'm not sure either change is necessary anyway: $@ means the target of the current rule, which should be the right thing here, shouldn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For variables with only a single character name, it's fine to use them without parens. This makefile behaves the same for calls to both ECHO and ECHO2:

ECHO = echo $1                                                                       
ECHO2 = echo $(1)                                                                    
                                                                                     
foo: ci/*.sh                                                                         
        $(call ECHO,$<)                                                              
        $(call ECHO2,$<) 

I was a little bit uneasy leaving it as $@ because it makes assumptions about where the WASM_STRIP macro will be used (always in a rule context), while being explicit about it being a macro and using $1 felt like it encoded the intent a little better.

I sort of wish that make didn't allow macros to be introduced with = :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I missed the last paragraph of the variable references section. Got it.

I wonder, could the conditional be shoved into the rule directly in a way that's more clear? I dunno, maybe like this:

	test -z "$(findstring g,$(CXX_OPT))" && which wasm-opt >/dev/null && wasm-opt --strip-debug -o $@ $@

I'm not convinced that looking for the single letter "g" makes sense here either, but maybe it's best to leave that alone. I suppose it works if you pass either -Og or -g?

Copy link
Contributor Author

@elliottt elliottt Jun 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'll definitely match unrelated occurrences of g in CXX_OPT. We could search for explicitly -g, but that will still match substrings.

distclean: clean
$(RM) $(FSM_DEP) compiler_flags

# technically this depends on the value of the FSM_CPP variable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could safely add $(FSM_CPP) to the dependencies of this rule to express what this comment says.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want it to depend on the files, only the state of that variable. I could pipe them into the compiler_flags file as well though...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, I get it. Well, maybe the rule runs fast enough that you could mark it as .PHONY and not worry about its dependencies?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entirely reasonable! I'll make that change.

done; \
echo; \
echo ']' \
) > "$@"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All I know about compile_commands.json is that when I tried to generate one once I got confused and gave up. Is this the best way to do it? I thought I remembered clang having an option to generate it for you, maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If clang can do it automatically, that would be better. This version doesn't feel ideal, but does produce a working compile_commands.json :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick googling didn't turn up anything that automatically generates compile_commands.json, and my experience with compile_commands.json from bazel and cmake is that it's generated by the build system, not clang/clangd. How do you feel about using this hacky version for now, and replacing it with something more robust when we find it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we find it. It's entirely possible I gave up the last time because there isn't a nice option if your build system doesn't do it for you; I don't remember. Yeah, I'm satisfied, ship it!

Maybe we should discuss changing the build system here to something more capable. That's certainly not blocking this PR though.

@elliottt elliottt merged commit a25ab11 into main Jun 8, 2022
@elliottt elliottt deleted the trevor/compile_commands.json branch June 9, 2022 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants