This is an archive of the discontinued LLVM Phabricator instance.

[Basic] Detect Git submodule version in CMake
ClosedPublic

Authored by modocache on Jul 3 2017, 8:54 AM.

Details

Summary

When searching for Git version control information, libBasic's CMake
checks for the path '.git/logs/HEAD'. However, when LLVM is included as
a Git submodule, this path does not exist. Instead, it contains a '.git'
file with the following:

gitdir: ../../.git/modules/external/llvm

Where '../..' is the relative path to the root repository that contains
the LLVM Git submodule.

Because of this discrepancy, clang --version does not output source
control information if built from a Git submodule.

To fix, check whether '.git' is a directory or a file. If it's a
directory, simply use the '.git/logs/HEAD' path. If it's a file, read it
and check for the tell-tale sign of a Git submodule: the text "gitdir:".
If it exists, follow that path and use the 'logs/HEAD' at that location
instead. This allows not only the correct revision information to be
retrieved, but also uses a file that will change with each source
control revision.

Test Plan:

  1. Before applying this change, build Clang as a Git submodule in a repository that places it in external/clang, and confirm no revision information is output when clang --version is invoked (just "clang 5.0.0" is output, no Git hashes).
  2. Apply these changes and build Clang as a Git repository nested under llvm/tools/clang, and confirm that clang --version displays correct version information.
  3. Apply these changes and build Clang as a Git submodule using the structure described in (1), and confirm version control information is output as in (2).

Event Timeline

modocache created this revision.Jul 3 2017, 8:54 AM
jordan_rose requested changes to this revision.Jul 3 2017, 9:20 AM

If I'm remembering correctly from when I set this up, this isn't just about detecting which version control system you're using; it's about finding a file that will change on every commit. Otherwise, the generated Version.cpp won't be rebuilt after you update.

If you don't want to go looking for a better choice for this that would handle submodules, a stopgap answer would be to add a second entry that just looks for .git in addition to the one looking for HEAD.

This revision now requires changes to proceed.Jul 3 2017, 9:20 AM
modocache planned changes to this revision.Jul 5 2017, 1:23 PM

Oh, nice catch @jordan_rose, you're absolutely right. I just tried updating my Git submodule reference for Clang and rebuilding my project, but the commit hash shown for Clang didn't change accordingly.

I'll need to find a file that changes on every commit. Following the Git submodule path, gitdir: ../../.git/modules/external/llvm and checking for ../../.git/modules/external/llvm/HEAD appears to work. I might rewrite the patch to do that, or try migrating this to use LLVM's source control checking (I think it exists in llvm/cmake/modules/VersionFromVCS.cmake).

pcc added a subscriber: pcc.Jul 5 2017, 1:30 PM

FYI, I don't think HEAD on its own will work because it is not necessarily updated on every commit, see discussion on D31985.

I'm not sure why we would care if a commit is made on a branch. The important information here is what commit is checked out, and that's what HEAD refers to.

modocache updated this revision to Diff 105673.Jul 7 2017, 12:25 PM
modocache edited edge metadata.

Use submodule's .git directory.

modocache updated this revision to Diff 105674.Jul 7 2017, 12:27 PM
modocache edited the summary of this revision. (Show Details)
modocache removed a subscriber: pcc.

Update commit message.

Harbormaster completed remote builds in B8058: Diff 105674.
jordan_rose added inline comments.Jul 10 2017, 2:17 PM
lib/Basic/CMakeLists.txt
27

How about

if("${file_contents}" MATCHES "^gitdir: ([^\n]+)")
  set(git_path "${git_path}${CMAKE_MATCH_0}")
endif()

and then no stripping or replacing later at all? This admittedly doesn't handle some future submodule format that doesn't put gitdir on the first line, but neither does the code that's there.

(This also doesn't handle absolute path submodule references, but looking around a bit makes it sound like those aren't supposed to occur in practice and are considered bugs when git does generate them. I could be wrong about that though.)

modocache updated this revision to Diff 106367.Jul 12 2017, 7:18 PM

Use CMAKE_MATCH_0 instead of using REGEX REPLACE. Thanks for the suggestion!

modocache marked an inline comment as done.Jul 12 2017, 7:21 PM

Friendly ping! I'm pretty excited about this change, it helps a pet project of mine, which builds Clang and LLVM checked out as submodules, display correct revision information. Let me know if I can modify this change at all, to make it easier to accept.

jordan_rose accepted this revision.Jul 17 2017, 10:31 AM

Whoops, yes, this new version looks good!

This revision is now accepted and ready to land.Jul 17 2017, 10:31 AM
modocache closed this revision.Jul 17 2017, 12:23 PM