[llvm-dev] Understanding the version handling in LLVM/Clang/LLD

Sedat Dilek via llvm-dev llvm-dev at lists.llvm.org
Thu May 21 03:45:00 PDT 2020


[ Please CC me I ma not subcribed to this mailing-list ]

[ CC Tom and Hans as LLVM/stable maintainers ]

Hi,

I want to understand the version handling in LLVM/Clang/LLD.

Normally, I build from "release/10.x" Git branch by using the tool
tc-build from ClangBuiltLinux project.

With "llvm-10.0.1-rc1" Git tag I was able to setup a llvm-toolchain
consisting of the projects "clang" and "lld".

A Linux v5.7-rc6 was successfully built.

$ cat /proc/version
Linux version 5.7.0-rc6-2-amd64-clang (sedat.dilek at gmail.com@iniza)
(ClangBuiltLinux clang version 10.0.1
(https://github.com/llvm/llvm-project
f79cd71e145c6fd005ba4dd1238128dfa0dc2cb6), LLD 10.0.1
(https://github.com/llvm/llvm-project
f79cd71e145c6fd005ba4dd1238128dfa0dc2cb6)) #2~bullseye+dileks1 SMP
2020-05-20

I remember when I used official tarballs for RC releases, the version
string should look like:

$ clang-10 --version
dileks clang version 10.0.1rc1
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/dileks/src/llvm-toolchain/install/bin

$ ld.lld --version
LLD 10.0.1rc1 (compatible with GNU linkers)

$ llvm-as --version
LLVM (http://llvm.org/):
  LLVM version 10.0.1rc1
  Optimized build.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: sandybridge

My first change:

[ llvm/CMakeLists.txt ]

 if(NOT DEFINED LLVM_VERSION_SUFFIX)
-  set(LLVM_VERSION_SUFFIX "")
+  set(LLVM_VERSION_SUFFIX "rc1")
 endif()

Unfortunately, clang-10 and ld.lld binaries did not show this in their version.

So, I modified clang...

[ clang/CMakeLists.txt ]

-# Unlike PACKAGE_VERSION, CLANG_VERSION does not include LLVM_VERSION_SUFFIX.
-set(CLANG_VERSION
"${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}.${CLANG_VERSION_PATCHLEVEL}")
+if(NOT DEFINED CLANG_VERSION_SUFFIX)
+  set(CLANG_VERSION_SUFFIX ${LLVM_VERSION_SUFFIX})
+endif()
+# CLANG_VERSION includes LLVM_VERSION_SUFFIX.
+set(CLANG_VERSION
"${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}.${CLANG_VERSION_PATCHLEVEL}${CLANG_VERSION_SUFFIX}")

...and lld (the same way clang handles its version):

[ lld/CMakeLists.txt ]

-# Compute the LLD version from the LLVM version.
-string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLD_VERSION
-  ${PACKAGE_VERSION})
+# If LLD_VERSION_* is specified, use it, if not use LLVM_VERSION_*.
+if(NOT DEFINED LLD_VERSION_MAJOR)
+  set(LLD_VERSION_MAJOR ${LLVM_VERSION_MAJOR})
+endif()
+if(NOT DEFINED LLD_VERSION_MINOR)
+  set(LLD_VERSION_MINOR ${LLVM_VERSION_MINOR})
+endif()
+if(NOT DEFINED LLD_VERSION_PATCHLEVEL)
+  set(LLD_VERSION_PATCHLEVEL ${LLVM_VERSION_PATCH})
+endif()
+if(NOT DEFINED LLD_VERSION_SUFFIX)
+  set(LLD_VERSION_SUFFIX ${LLVM_VERSION_SUFFIX})
+endif()
+# LLD_VERSION includes LLVM_VERSION_SUFFIX.
+set(LLD_VERSION
"${LLD_VERSION_MAJOR}.${LLD_VERSION_MINOR}.${LLD_VERSION_PATCHLEVEL}${LLD_VERSION_SUFFIX}")
 message(STATUS "LLD version: ${LLD_VERSION}")

-string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" LLD_VERSION_MAJOR
-  ${LLD_VERSION})
-string(REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" LLD_VERSION_MINOR
-  ${LLD_VERSION})
-

That worked like expected for clang-10 and ld.lld with "-v" and/or
"--version" options.

A clang-test FAILED... Preprocessor/iwithprefix.c (below when using
LLVM_VERSION_SUFFIX = "git"):

This is because of the "rc1" string in the include path ("git" accordingly):

   lib/clang/10.0.1rc1/include

To fix this up (maybe someone can help to recognize "git" and "rc[1-9]"):

[ clang/test/Preprocessor/iwithprefix.c ]

-// CHECK: {{/|\\}}lib{{(32|64)?}}{{/|\\}}clang{{/|\\}}{{[.0-9]+}}{{/|\\}}include
+// CHECK: {{/|\\}}lib{{(32|64)?}}{{/|\\}}clang{{/|\\}}{{[.0-9]+}}rc1{{/|\\}}include

I guess this is due to my introduction and usage of CLANG_VERSION_SUFFIX.

Finally, I looked into master Git where I saw:

if(NOT DEFINED LLVM_VERSION_SUFFIX)
  set(LLVM_VERSION_SUFFIX "git")
endif()

And re-checked every place where especially...
   ${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX}
...is used.

So, I fixed it up by pre-checking for... if(LLVM_VERSION_SUFFIX STREQUAL "git")

Example (full patch attached):

[ llvm/cmake/modules/AddLLVM.cmake ]

@@ -541,11 +541,18 @@ function(llvm_add_library name)
     # Set SOVERSION on shared libraries that lack explicit SONAME
     # specifier, on *nix systems that are not Darwin.
     if(UNIX AND NOT APPLE AND NOT ARG_SONAME)
-      set_target_properties(${name}
-        PROPERTIES
-        # Since 4.0.0, the ABI version is indicated by the major version
-        SOVERSION ${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX}
-        VERSION ${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX})
+      # Since 4.0.0, the ABI version is indicated by the major version
+      if(LLVM_VERSION_SUFFIX STREQUAL "git")
+       set_target_properties(${name}
+          PROPERTIES
+         SOVERSION ${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX}
+         VERSION ${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX})
+      else()
+        set_target_properties(${name}
+          PROPERTIES
+         SOVERSION ${LLVM_VERSION_MAJOR}
+         VERSION ${LLVM_VERSION_MAJOR})
+      endif()
     endif()
   endif()

@@ -567,8 +574,13 @@ function(llvm_add_library name)
       if(${output_name} STREQUAL "output_name-NOTFOUND")
         set(output_name ${name})
       endif()
-      set(library_name
${output_name}-${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX})
-      set(api_name
${output_name}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}${LLVM_VERSION_SUFFIX})
+      if(LLVM_VERSION_SUFFIX STREQUAL "git")
+        set(library_name
${output_name}-${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX})
+        set(api_name
${output_name}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}${LLVM_VERSION_SUFFIX})
+      else()
+       set(library_name ${output_name}-${LLVM_VERSION_MAJOR})
+        set(api_name
${output_name}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH})
+      endif()
       set_target_properties(${name} PROPERTIES OUTPUT_NAME ${library_name})
       llvm_install_library_symlink(${api_name} ${library_name} SHARED

In the end I was able to build a LLVM/Clang/LLD toolchain which shows
me "10.0.1rc1" version string for all llvm-*, clang-10 and ld.lld
binaries.

As I understand the llvm/stable maintainers do not use or bump
LLVM_VERSION_SUFFIX with RC releases as I have expected.

But I see some problems when people do not use "git" as value in
LLVM_VERSION_SUFFIX - like me "rc1".

Also, I see an inconsistency for llvm-* binaries when using "git"
whereas Clang and LLD do not show this in their version strings.

I am not sure what the introduction of CLANG_VERSION_SUFFIX and
LLD_VERSION_SUFFIX is all doing.

The only value used for LLVM_VERSION_SUFFIX is "git" in master Git branch.

Where is LLVM_VERSION_SUFFIX really relevant?
What do you think of the usage of LLVM_VERSION_SUFFIX in general?

What do you think to the changes to Clang and LLD versioning?

Thanks.

Regards,
- Sedat -

P.S.: Some useful outputs

FAIL: Clang :: Preprocessor/iwithprefix.c (8758 of 16586)
******************** TEST 'Clang :: Preprocessor/iwithprefix.c' FAILED
********************
Script:
--
: 'RUN: at line 3';   rm -rf
/home/dileks/src/llvm-toolchain/build/stage1/tools/clang/test/Preprocessor/Output/iwithprefix.c.tmp.tmps
: 'RUN: at line 4';   mkdir -p
/home/dileks/src/llvm-toolchain/build/stage1/tools/clang/test/Preprocessor/Output/iwithprefix.c.tmp.tmps/first
/home/dileks/src/llvm-toolchain/build/stage1/tools/clang/test/Preprocessor/Output/iwithprefix.c.tmp.tmps/second
: 'RUN: at line 5';
/home/dileks/src/llvm-toolchain/build/stage1/bin/clang -cc1
-internal-isystem
/home/dileks/src/llvm-toolchain/build/stage1/lib/clang/10.0.1git/include
-nostdsysteminc -triple x86_64-unknown-unknown    -iprefix
/home/dileks/src/llvm-toolchain/build/stage1/tools/clang/test/Preprocessor/Output/iwithprefix.c.tmp.tmps/
-iwithprefix second     -isystem
/home/dileks/src/llvm-toolchain/build/stage1/tools/clang/test/Preprocessor/Output/iwithprefix.c.tmp.tmps/first
-v /home/dileks/src/llvm-toolchain/tc-build/llvm-project/clang/test/Preprocessor/iwithprefix.c
2> /home/dileks/src/llvm-toolchain/build/stage1/tools/clang/test/Preprocessor/Output/iwithprefix.c.tmp.out
: 'RUN: at line 8';
/home/dileks/src/llvm-toolchain/build/stage1/bin/FileCheck
/home/dileks/src/llvm-toolchain/tc-build/llvm-project/clang/test/Preprocessor/iwithprefix.c
< /home/dileks/src/llvm-toolchain/build/stage1/tools/clang/test/Preprocessor/Output/iwithprefix.c.tmp.out
--
Exit Code: 1

Command Output (stderr):
--
/home/dileks/src/llvm-toolchain/tc-build/llvm-project/clang/test/Preprocessor/iwithprefix.c:12:11:
error: CHECK: expected string not found in input
// CHECK: {{/|\\}}lib{{(32|64)?}}{{/|\\}}clang{{/|\\}}{{[.0-9]+}}{{/|\\}}include
          ^
<stdin>:6:2: note: scanning from here
 /home/dileks/src/llvm-toolchain/build/stage1/lib/clang/10.0.1git/include
 ^
<stdin>:6:45: note: possible intended match here
 /home/dileks/src/llvm-toolchain/build/stage1/lib/clang/10.0.1git/include

[ scripts/run_tests_20200520.sh ]

#!/bin/sh

export LANG=C
export LC_ALL=C

CLANG_TESTS="Preprocessor/iwithprefix.c"

LLVM_LIT_OPTS="--verbose --echo-all-commands --show-all"

cd build/stage1/

for t in $CLANG_TESTS ; do ./bin/llvm-lit $LLVM_LIT_OPTS
./tools/clang/test/$t ; done

- EOT -


More information about the llvm-dev mailing list