If `-Dprotobuf_USE_EXTERNAL_GTEST=ON` is passed to CMake, it will use an external Google Test copy (i.e. by calling `find_package(GTest REQUIRED)`) rather than the one provided as a submodule.
This makes sense for larger projects that might already include Google Test and want to use a more standard CMake approach.
Also updated build instructions with this information, and more idiomatic usage.
Co-authored-by: Adam Cozzette <acozzette@google.com>
Convenience feature: enable users to test via the familiar `ctest` command rather than making the `check` target.
They would be able to use the familiar CMake pattern:
```
cmake -S source/protobuf -B build/protobuf ...
cmake --build build/protobuf
ctest --test-dir build/protobuf
cmake --install build/protobuf
```
This is a follow-up to 9f447fc9d3da93da29b8301f1a8ca57b1ea812d7
This updates the CMake support to additionally symlink the soversion value
to the generated shared library when so generated. This aligns the
generated soversion with that traditionally used by the Makefile build
workflow and provides cross-compatibility irrespective of build approach
used.
The primary version of the non-symlink library retains the actual
(non-SO) project version for clarity and compatibility with
installations built using prior versions of CMake support. An example of
the net resulting symlink structures is shown below, where the most
important aspect is that the symlink matching the embedded SONAME is
present (libprotobuf.so.30 in the example case).
Makefile:
libprotobuf.so -> libprotobuf.so.30.0.0
libprotobuf.so.30 -> libprotobuf.so.30.0.0
libprotobuf.so.30.0.0
CMake:
libprotobuf.so -> libprotobuf.so.30
libprotobuf.so.30 -> libprotobuf.so.3.19.0.0
libprotobuf.so.3.19.0.0
Fixes: #8635
when using CMake >= 3.15, we use CMAKE_MSVC_RUNTIME_LIBRARY
to reproduce the /MT vs /MD when protobuf_MSVC_STATIC_RUNTIME
is TRUE or FALSE
MultiThreaded is for /MT
MultiThreadedDebug is for /MTd
MultiThreadedDLL is for /MD
MultiThreadedDebugDLL is for /MDd
This is based on @haberman's changes in #8257. Now that we're using
std::mutex we no longer need to check whether pthreads are available, so
this commit removes references to HAVE_PTHREAD. I left the autotools
build alone, though, since we are likely to drop support for it soon
anyway.
The `VERSION_GREATER_EQUAL` operator was introduced in CMake 3.7.0
(released in 2016). Use the long form of the check by splitting the
operation into two comparisons to support the older CMake.
When using a new enough CMake (3.15+) prefer to use the
`MSVC_RUNTIME_LIBRARY` property on targets to select the runtime library
variant. This property is automatically set to the value specified by
`CMAKE_MSVC_RUNTIME_LIBRARY`. This property requires that the CMake
Policy 91 is set to new (see CMP0091).
The primary motivation for this change is to avoid referring to the
`upb_msglayout` object when we are trying to fetch the `upb_msglayout`
object for a sub-message. This will help pave the way for parsing
extensions. We also implement several optimizations so that we can
make this change without regressing performance.
Normally we compute the layout for a sub-message field like so:
```
const upb_msglayout *get_submsg_layout(
const upb_msglayout *layout,
const upb_msglayout_field *field) {
return layout->submsgs[field->submsg_index]
}
```
The reason for this indirection is to avoid storing a pointer directly
in `upb_msglayout_field`, as this would double its size (from 12 to 24
bytes on 64-bit architectures) which is wasteful as this pointer is
only needed for message typed fields.
However `get_submsg_layout` as written above does not work for
extensions, as they will not have entries in the message's
`layout->submsgs` array by nature, and we want to avoid creating
an entire fake `upb_msglayout` for each such extension since that
would also be wasteful.
This change removes the dependency on `upb_msglayout` by passing down
the `submsgs` array instead:
```
const upb_msglayout *get_submsg_layout(
const upb_msglayout *const *submsgs,
const upb_msglayout_field *field) {
return submsgs[field->submsg_index]
}
```
This will pave the way for parsing extensions, as we can more easily
create an alternative `submsgs` array for extension fields without
extra overhead or waste.
Along the way several optimizations presented themselves that allow
a nice increase in performance:
1. Passing the parsed `wireval` by address instead of by value ended
up avoiding an expensive and useless stack copy (this is on Clang,
which was used for all measurements).
2. When field numbers are densely packed, we can find a field by number
with a single indexed lookup instead of linear search. At codegen
time we can compute the maximum field number that will allow such
an indexed lookup.
3. For fields that do require linear search, we can start the linear
search at the location where we found the previous field, taking
advantage of the fact that field numbers are generally increasing.
4. When the hasbit index is less than 32 (the common case) we can use
a less expensive code sequence to set it.
5. We check for the hasbit case before the oneof case, as optional
fields are more common than oneof fields.
Benchmark results indicate a 20% improvement in parse speed with a
small code size increase:
```
name old time/op new time/op delta
ArenaOneAlloc 21.3ns ± 0% 21.5ns ± 0% +0.96% (p=0.000 n=12+12)
ArenaInitialBlockOneAlloc 6.32ns ± 0% 6.32ns ± 0% +0.03% (p=0.000 n=12+10)
LoadDescriptor_Upb 53.5µs ± 1% 51.5µs ± 2% -3.70% (p=0.000 n=12+12)
LoadAdsDescriptor_Upb 2.78ms ± 2% 2.68ms ± 0% -3.57% (p=0.000 n=12+12)
LoadDescriptor_Proto2 240µs ± 0% 240µs ± 0% +0.12% (p=0.001 n=12+12)
LoadAdsDescriptor_Proto2 12.8ms ± 0% 12.7ms ± 0% -1.15% (p=0.000 n=12+10)
Parse_Upb_FileDesc<UseArena,Copy> 13.2µs ± 2% 10.7µs ± 0% -18.49% (p=0.000 n=10+12)
Parse_Upb_FileDesc<UseArena,Alias> 11.3µs ± 0% 9.6µs ± 0% -15.11% (p=0.000 n=12+11)
Parse_Upb_FileDesc<InitBlock,Copy> 12.7µs ± 0% 10.3µs ± 0% -19.00% (p=0.000 n=10+12)
Parse_Upb_FileDesc<InitBlock,Alias> 10.9µs ± 0% 9.2µs ± 0% -15.82% (p=0.000 n=12+12)
Parse_Proto2<FileDesc,NoArena,Copy> 29.4µs ± 0% 29.5µs ± 0% +0.61% (p=0.000 n=12+12)
Parse_Proto2<FileDesc,UseArena,Copy> 20.7µs ± 2% 20.6µs ± 2% ~ (p=0.260 n=12+11)
Parse_Proto2<FileDesc,InitBlock,Copy> 16.7µs ± 1% 16.7µs ± 0% -0.25% (p=0.036 n=12+10)
Parse_Proto2<FileDescSV,InitBlock,Alias> 16.5µs ± 0% 16.5µs ± 0% +0.20% (p=0.016 n=12+11)
SerializeDescriptor_Proto2 5.30µs ± 1% 5.36µs ± 1% +1.09% (p=0.000 n=12+11)
SerializeDescriptor_Upb 12.9µs ± 0% 13.0µs ± 0% +0.90% (p=0.000 n=12+11)
FILE SIZE VM SIZE
-------------- --------------
+1.5% +176 +1.6% +176 upb/decode.c
+1.8% +176 +1.9% +176 decode_msg
+0.4% +64 +0.4% +64 upb/def.c
+1.4% +64 +1.4% +64 _upb_symtab_addfile
+1.2% +48 +1.4% +48 upb/reflection.c
+15% +32 +18% +32 upb_msg_set
+2.9% +16 +3.1% +16 upb_msg_mutable
-9.3% -288 [ = ] 0 [Unmapped]
[ = ] 0 +0.2% +288 TOTAL
```