Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP prototype clang-format support #889

Closed
wants to merge 1 commit into from
Closed

WIP prototype clang-format support #889

wants to merge 1 commit into from

Conversation

aqnuep
Copy link
Collaborator

@aqnuep aqnuep commented Mar 29, 2024

This is largely WIP at this point.

@aqnuep aqnuep force-pushed the clang-format branch 2 times, most recently from 948dc38 to 49f11fb Compare April 3, 2024 08:50
@aqnuep
Copy link
Collaborator Author

aqnuep commented Apr 3, 2024

@MarkCallow, this is still WIP as I still have to update the auto-generated files and their scripts to include /* clang-format off */ in order to avoid auto-formatting them, and add clang-tidy support. However, this branch already includes the following:

  • Moving external dependencies to the external directory
  • Adding a set of clang-format files specific for the directories in question (e.g. lib has a special style file to allow return types on separate lines per the traditional convention)
  • Running clang-format across all files

Please check the code and let me know whether the new structure and code format seem reasonable to you.

@aqnuep
Copy link
Collaborator Author

aqnuep commented Apr 18, 2024

@MarkCallow, I did not yet get feedback from you about the proposed code formatting conventions applied in this branch.

Should I maybe create a separate PR first that just moves the external components into the external directory (and update build scripts accordingly) to do this step-by-step?

@MarkCallow
Copy link
Collaborator

@MarkCallow, I did not yet get feedback from you about the proposed code formatting conventions applied in this branch.

Sorry. I am a little under the weather so working when I feel up to it. I reckon reviewing this is going to take some extended concentration so I've been putting it off. Hopefully I'll feel up to taking a look tomorrow.

Should I maybe create a separate PR first that just moves the external components into the external directory (and update build scripts accordingly) to do this step-by-step?

That is not necessary.

I remain somewhat concerned that formatting is done as a workflow rather than via a clean filter run when files are commited. I have to think more about potential ramifications of the remove branch becoming different from what one has just pushed.

Are there any editors that can apply the same formatting during editing?

@MarkCallow
Copy link
Collaborator

What is the difference between "format" and "tidy"?

@aqnuep
Copy link
Collaborator Author

aqnuep commented Apr 18, 2024

I remain somewhat concerned that formatting is done as a workflow rather than via a clean filter run when files are commited. I have to think more about potential ramifications of the remove branch becoming different from what one has just pushed.

This is the practice used in other Khronos projects: modify, format (automatically or through explicit call), then commit. CI only checks that the modifications match the formatting rules.

Are there any editors that can apply the same formatting during editing?

Many editors have clang-format built-in, AFAICT, but I always do this manually so I don't have much experience with them.

What is the difference between "format" and "tidy"?

clang-format is only dealing with formatting, while clang-tidy is a "linter" and provides higher level analysis, see: https://clang.llvm.org/extra/clang-tidy/

Copy link
Collaborator

@MarkCallow MarkCallow left a comment

Choose a reason for hiding this comment

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

Here are some comments to start. Some of the comments refer to global things which I've listed here.

  • 1. Narrower line width
  • 2. { on same line as function name. There is no specific comment about this. I want to think about it. I've always put the { on a separate line except on inline functions defined within a class definition. I suppose it is better to be consistent.
  • 3. nesting (indent) of #if and #define
  • 4. case not indented
  • 5. namespace content not indented.

After my experience with this first pass, I think it would be better to make a separate PR for moving all the files. Note there is a comment about also moving etcdec.cxx.

I decided having the actions for format and tidy are fine. I want to investigate providing a clean filter people can install to do the formatting on commit, should they wish, and whether the editors I use can support this formatting during text entry.

(getAssetPath() + ktxfile).c_str(),
KTX_TEXTURE_CREATE_NO_FLAGS,
&kTexture);
ktxresult = ktxTexture_CreateFromNamedFile((getAssetPath() + ktxfile).c_str(), KTX_TEXTURE_CREATE_NO_FLAGS, &kTexture);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I prefer narrower lines because I can read narrower lines faster and I often have at 2 files open side-by-side in Xcode. I see the ColumnLimit is set to 132 in .clang-format. Is that the setting that affects line width? Let's see what it looks like with 80. If that is too little, given the length of some of the token names, we can try 100.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, 132 is the line width. Note that this (and many other rules) are the default ones used across other Khronos repositories. I think we should use at least 100 characters though as 80 is just too short for modern standards.

ktxresult = ktxTexture_VkUploadEx(kTexture, &kvdi, &texture,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
ktxresult = ktxTexture_VkUploadEx(kTexture, &kvdi, &texture, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a way to get it to put one parameter per line if the number of parameters exceeds some value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure, I'll have to look into that, but I would be surprised if clang-format wouldn't have an option for such a common style.

void
Texture::prepareSamplerAndView()
{
void Texture::prepareSamplerAndView() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you put the type on a separate line in .cpp file or will such a setting affect inline functions in class definitions as well?

Historically putting the name of a function at its definition at the very beginning of a line made for an easy way to find that definition. Probably less important for c++ because you don't often call a fully qualified name, e.g, Texture::prepareSamplerAndView, so a search for that will find the definition.

For both C and c modern IDEs have mechanisms to go to a definition so it is not as important as it used to be.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So this is an on/off option. I used return type on separate line for the libktx code because that was the style, but used return type on same line for newer things like the ktx CLI tools which use more modern style. If you could provide a list of directories where you'd like us to retain the legacy "return type on separate line" style, we can just configure things accordingly.

@@ -4,36 +4,32 @@
#pragma once

#if defined(KHRONOS_STATIC)
#define KTX_BASISU_API
#define KTX_BASISU_API
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess indenting # is not officially supported but every compiler we use supports it and, as far as I am concerned, it makes nested #ifs far easier to understand and less error prone.

Is it possible to get clang-format to indent them?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll look into whether there's a style option for that.

// For PVRTC1, Basis only writes (or requires) total_blocks * bytes_per_block. But GL requires extra padding for very small textures:
// https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
if (transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGB ||
transcoder_format == transcoder_texture_format::cTFPVRTC1_4_RGBA) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is is possible to have it put the operator at the start of the second line instead of the end of the first when making multi-line expressions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll have to look into that too.

@@ -1,9 +1,9 @@
/*
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should move this file to external/etcdec or similar so it is not reformatted. Strict adherence to the terms of the license require not modifying the file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the info, I didn't notice this is also an external file.

int dstChannels, dstChannelBytes;

switch (srcFormat) {
case GL_COMPRESSED_SIGNED_R11_EAC:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you indent the cases by 2 spaces? Since I'm always fighting editors to do this we probably shouldn't continue doing it but I'm curious.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We'll look into this as well.

# SPDX-License-Identifier: Apache-2.0
---
# Use defaults from the Google style with the following exceptions:
Language: Cpp
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this apply to the c files as well?

@@ -69,21 +69,21 @@ HMODULE ktxOpenGLModuleHandle;
#define GetOpenGLModuleHandle(flags) dlopen(NULL, flags)
#define LoadProcAddr dlsym
#define LIBRARY_NAME NULL
void* ktxOpenGLModuleHandle;
void *ktxOpenGLModuleHandle;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I saw the opposite change being made in basisu_c_binding.{cpp,h}, foo *bar became foo* bar. Why the difference here? Is it a c vs C thing? I prefer foo* bar because to my mind the type of "bar" is "pointer to foo".

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, this is one of those configurable things. We can go either way. The reason why this style is the default in the Google style because technically the "*" belongs to the variable name (imagine when multiple variables are declared in a comma separated list like int *a_ptr, b_value, *c_ptr;).

Copy link
Collaborator

Choose a reason for hiding this comment

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

My question here is why the difference in basisu_c_binding.* vs within the libktx code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a good question. Now that you say, I saw similar inconsistencies in clang-format behavior on other Khronos ecosystem repositories. Indeed could be a C vs C++ difference, but may also be something more subtle.

@@ -15,72 +15,71 @@
#include "vkformat_enum.h"

bool
isProhibitedFormat(VkFormat format)
{
isProhibitedFormat(VkFormat format) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Has the generator been modified to match the clang format or has clang modified this file? I don't see anything to tell clang to ignore it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

clang-format modified it.

For generated files we really have various options:

  1. Not format them at all (would require moving generated files into a dedicated folder marked to not format)
  2. Format them (by explicitly calling e.g. git clang-format before your commit) - kind of the current proposal
  3. Integrate calling clang-format into the generation process

Copy link
Collaborator

Choose a reason for hiding this comment

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

I thought you were going to modify the generators to add a line that tells clang_format not to touch the file and to output in whatever format we eventually settle on.

How does clang-format get installed on one's system? My concern is for when we eventually move to generating the VkFormat related files from vk.xml in the Vulkan-Docs repo. Will #3 require installing clang-format in that repo.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So it is an option to not auto-format the generated files, but then they also need to be moved to a dedicated directory, because clang-format styles can only be changed (in this case disabled) per directory.

It's up to us whether we want to do that instead, but with this prototype I proposed that it may be best to just format them as other files (and after they are regenerated they are also reformatted using git clang-format, per normal).

Copy link
Collaborator

Choose a reason for hiding this comment

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

but then they also need to be moved to a dedicated directory, because clang-format styles can only be changed (in this case disabled) per directory.

What happened to this?

I still have to update the auto-generated files and their scripts to include /* clang-format off */ in order to avoid auto-formatting them,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh you're right. I completely forgot that's what we agreed on with @lexaknyazev.

@MarkCallow
Copy link
Collaborator

Shall we close this now that #913 exists?

@aqnuep
Copy link
Collaborator Author

aqnuep commented Jun 5, 2024

Yes, closing.

@aqnuep aqnuep closed this Jun 5, 2024
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.

None yet

2 participants