Revamp how BoringSSL generate prefix header on ObjC#21194
Conversation
|
@jtattermusch - could you take an initial look at this PR and let me know if it makes sense to you? Most of the contents here reflect our discussions in the doc. The only caveat that I feel a bit uncomfortable is that the |
| @@ -0,0 +1,249 @@ | |||
| %YAML 1.2 | |||
There was a problem hiding this comment.
what is this file with .template-e suffix?
There was a problem hiding this comment.
I'm not sure... probably created a copy with a typo. I'm removing this file.
| # SOME_BORINGSSL_SYMBOL | ||
| sed -i'.back' '/^#define.*\\\\$/{N;/^#define \\([A-Za-z0-9_]*\\) *\\\\\\n *\\1/d;}' include/openssl/*.h | ||
| # Grab prefix header from Github repo | ||
| curl -o include/openssl/boringssl_prefix_symbols.h -L https://raw.githubusercontent.com/grpc/grpc/master/src/objective-c/boringssl_prefix_headers/boringssl_prefix_symbols-${boringssl_commit}.h |
There was a problem hiding this comment.
I understand the challenge here, but this downloads the right version of boringssl_prefix_symbols (depending on boringssl's SHA) from master of our repository. That means we'd have to keep an ever-growing list of boringssl shadow headers in master of our repository forever (one version for each SHA we use), and that's not a good solution.
Also I don't like that the download command can fail and that can lead to random errors when building.
Would inlining a base64 gzip compressed version of boringssl_prefix_symbols.h fit in the podspec? I know it's dirty but it's better than the challenges of this approach.
Checking in a generated version of boringssl_prefix_symbols.h into our repo is fine, but then regenerating project could inline the base64 compressed version of it into the podspec (which make the podspec standalone).
There was a problem hiding this comment.
I tried this and
gzip -c boringssl_prefix_symbols.h | base64 >boringssl_prefix_symbols.h.gz.base64 gives you a file 37KB in size.
That should be good enough for us.
$ ls -lh
total 320K
-rw-r----- 1 jtattermusch primarygroup 278K Nov 21 08:34 boringssl_prefix_symbols-7f02881e96e51f1873afcf384d02f782b48967ca.h
-rw-r----- 1 jtattermusch primarygroup 37K Nov 21 08:36 boringssl_prefix_symbols.h.gz.base64
| s.prefix_header_contents = | ||
| ${expand_symbol_list(settings.grpc_shadow_boringssl_symbols)} | ||
| # Xcode import style. We add it here so that Xcode knows where to find it. | ||
| find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <boringssl_prefix_symbols.h>;#include <openssl_grpc/boringssl_prefix_symbols.h>;g' |
There was a problem hiding this comment.
seems dirty, can we avoid this line?
There was a problem hiding this comment.
I don't think so because if users build their projects as Framework, Apple does require Framework name to be the first segment in the include statement (see Apple's doc). The only possible way to avoid it is to hack the "Header search path" of the generated gRPC-Core and BoringSSL-GRPC targets pointing to the downloaded BoringSSL repo. Not sure if it'll work for Framework (because in that case the two targets are including a header outside of the Framework's Header directory). And if it works, IMHO it's an even more dirty hack.
There was a problem hiding this comment.
Ok, so just to make sure: does this basically replace all occurrences of #include <boringssl_prefix_symbols.h> with #include <openssl_grpc/boringssl_prefix_symbols.h> in all *.h, *.cc and *.c files?
If so, then fair, it's not super clean, but acceptable.
| # Do the following in grpc root directory | ||
| cd ../.. | ||
|
|
||
| docker build tools/dockerfile/grpc_objc/generate_boringssl_prefix_header -t grpc/boringssl_prefix_header |
There was a problem hiding this comment.
do we really need docker for this, it seems that generating the prefix header should work just fine on people's workstation?
It look like you need 3 non-trivial scripts upgrade_boringssl_objc.sh, Dockerfile and generate_boringssl_prefix_header.sh to update the prefix header, so I'm not sure this actually simplifies things?
There was a problem hiding this comment.
I am using Docker for a few reasons:
- People also use Mac for the same purpose too (this process is for ObjC). Installing dependencies on Mac is not as trivial as on Linux.
- I tend to not mess with user's workspace. As you see the process involves building BoringSSL and creating a symbol list file. The BoringSSL in the user's workspace may have their own changes. And I do need to
rm -rfthe artifacts which makes me a bit uncomfortable. Docker just get rid of all those matters. - We are already using Docker in
tools/distrib/clang_format_code.sh.
As to your question, even if we do not use Docker, it would be pretty much combining the 2 shell scripts into one; I don't think there's much to remove there other than the Docker related lines. So I don't think Docker complicate things too.
There was a problem hiding this comment.
I'd argue most people don't have docker installed on their macs, so arguably this doesn't really make things easier (you'd need to install docker on mac and build the images first which takes time) but it does make all the scripts more complicated.
I'd prefer if we provided a robust script for regenerating the .h file (that assumes golang a cmake are installed, both are easy to install on mac). We can look into using docker in a followup PR and see if it could further simplify things.
Also, for now just supporting regenerating the prefix .h on linux is completely acceptable - later we can make improvements.
|
|
||
| [ $# == 1 ] || { echo "Usage: generate_boringssl_prefix_header.sh <boringssl_commit>" ; exit 1 ; } | ||
|
|
||
| git clone -n https://github.com/google/boringssl.git |
There was a problem hiding this comment.
seems completely unnecessary. You have the right commit of boringssl in third_party/boringssl already so why this?
There was a problem hiding this comment.
Part of the reason was I did not find a way to cleanly copy both /tools/dockerfile/grpc_objc/generate_boringssl_prefix_header/generate_boringssl_prefix_header.sh and /third_party/boringssl into the container. To make it possible I probably need to set the Docker build context to be gRPC's root dir, but that means transferring the entire grpc directory to Docker when running docker build, which takes much more time than git clone when I tried it.
And also for the same sanity reason as above, it does not cost too much to get a clean version of BoringSSL.
eb8f619 to
ed01a6b
Compare
jtattermusch
left a comment
There was a problem hiding this comment.
I think overall this is going in the right direction but I have a few simplification requests - please see comments.
| # outputs a gzip+base64 encoded version of boringssl_prefix_symbols.h because of Cocoapods' | ||
| # limit on the 'prepare_command' field length. The encoded header is put at | ||
| # /src/boringssl/boringssl_prefix_symbols.h.gz.b64. Here we decode the content and inject | ||
| # the header to correcty location in BoringSSL. |
There was a problem hiding this comment.
nit: s/correcty/the correct/ ?
| s.prefix_header_contents = | ||
| ${expand_symbol_list(settings.grpc_shadow_boringssl_symbols)} | ||
| # Xcode import style. We add it here so that Xcode knows where to find it. | ||
| find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <boringssl_prefix_symbols.h>;#include <openssl_grpc/boringssl_prefix_symbols.h>;g' |
There was a problem hiding this comment.
Ok, so just to make sure: does this basically replace all occurrences of #include <boringssl_prefix_symbols.h> with #include <openssl_grpc/boringssl_prefix_symbols.h> in all *.h, *.cc and *.c files?
If so, then fair, it's not super clean, but acceptable.
| # /src/boringssl/boringssl_prefix_symbols.h.gz.b64. Here we decode the content and inject | ||
| # the header to correcty location in BoringSSL. | ||
| base64 -D <<EOF | gunzip > include/openssl/boringssl_prefix_symbols.h | ||
| % for line in open("src/boringssl/boringssl_prefix_symbols.h.gz.b64", "r").readlines(): |
There was a problem hiding this comment.
For better readability (being able to see diffs over versions etc., perhaps it would be better to check-in only the boringssl_prefix_symbols.h file as (src/boringssl/boringssl_prefix_symbols.h) and only perform the gzip compression and base64 encoding in the .template. That way the generated podspec will have the gz.b64 version of the headers, but we won't have a cryptic encoded file checked into our repository.
One would also be able to see the diffs in .h over versions, which can come very handy when trying to troubleshoot boringssl upgrades in the future (one can clearly see which symbols were added etc - very useful).
It should be pretty easy to perform gz and b64 with python code inside the template.
There was a problem hiding this comment.
This should work, but the problem I meet right now is that python 2's gzip library has a bug that using gzip.compress(...) will report AttributeError: 'module' object has no attribute 'compress'. This does not happen on python 3. It happens on both my mac and my Linux. I'll check if Kokoro has the same error (still running as for now), but I guess a lot of the team's machines could have the same problem.
There was a problem hiding this comment.
@jtattermusch - did we switch to python 3? Somehow I remember we dropped python 2 last year.
There was a problem hiding this comment.
ignore, this is resolved
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # Generate the list of boringssl symbols that need to be shadowed based on the |
There was a problem hiding this comment.
nit: the comment is out of date - looks like this is intended to be a script to perform the full update of boringssl version, not just updating the shadow list.
| [ -f ssl/libssl.a ] || { echo "Failed to build libssl.a" ; exit 1 ; } | ||
| [ -f crypto/libcrypto.a ] || { echo "Failed to build libcrypto.a" ; exit 1 ; } | ||
|
|
||
| go run ../util/read_symbols.go ssl/libssl.a > ./symbols.txt |
There was a problem hiding this comment.
qq: where are the steps to obtain boringssl_prefix_symbols.h coming from? Are they extracted from the boringssl build? If so, please add a note and link to the original location.
There was a problem hiding this comment.
Are they extracted from the boringssl build?
Yes
| cpu_cost: 1000 | ||
| - script: tools/distrib/check_protobuf_pod_version.sh | ||
| - script: tools/distrib/check_shadow_boringssl_symbol_list.sh | ||
| - script: tools/distrib/check_boringssl_prefix_symbol.sh |
There was a problem hiding this comment.
I think a cleaner and faster solution would be if boringssl_prefix_symbols.h would start with
// generated by generate_boringssl_prefix_header.sh from boringssl [THE-COMMIT-SHA] (just add that line when generating the file)
and sanity check would just check that boringssl_prefix_symbols.h has the right header.
That way you could make the check in seconds and you wouldn't need to add cmake to the sanity docker file.
| mkdir -p $BORINGSSL_PREFIX_HEADERS_DIR | ||
| docker run -it --rm -v $(pwd)/$BORINGSSL_PREFIX_HEADERS_DIR:/output grpc/boringssl_prefix_header $BORINGSSL_COMMIT | ||
|
|
||
| # Increase the minor version by 1 |
There was a problem hiding this comment.
I don't like that this script is not idempotent - if you run it multiple times, it will keep increasing the version number.
IMHO just having a robust .sh that regenerates the boringssl_prefix_symbols.h is enough for this script.
If you want to add a script that automates the whole boringssl update process, we can look into that but there are questions to be answered first and it doesn't belong to this PR. I'd recommend turning this script into something that just generates the header file (with use of docker if you will).
|
|
||
| docker build tools/dockerfile/grpc_objc/generate_boringssl_prefix_header -t grpc/boringssl_prefix_header | ||
| mkdir -p $BORINGSSL_PREFIX_HEADERS_DIR | ||
| docker run -it --rm -v $(pwd)/$BORINGSSL_PREFIX_HEADERS_DIR:/output grpc/boringssl_prefix_header $BORINGSSL_COMMIT |
There was a problem hiding this comment.
I suspect without changing the UID, the generated file will end up being owned by root.
grpc/tools/distrib/clang_format_code.sh
Line 30 in 2e4ebd7
| # Do the following in grpc root directory | ||
| cd ../.. | ||
|
|
||
| docker build tools/dockerfile/grpc_objc/generate_boringssl_prefix_header -t grpc/boringssl_prefix_header |
There was a problem hiding this comment.
I'd argue most people don't have docker installed on their macs, so arguably this doesn't really make things easier (you'd need to install docker on mac and build the images first which takes time) but it does make all the scripts more complicated.
I'd prefer if we provided a robust script for regenerating the .h file (that assumes golang a cmake are installed, both are easy to install on mac). We can look into using docker in a followup PR and see if it could further simplify things.
Also, for now just supporting regenerating the prefix .h on linux is completely acceptable - later we can make improvements.
|
Come on brother, we are looking forward to solving this problem as soon as possible. |
|
@jtattermusch - Updated according to your last comments. PTAL. |
|
@jtattermusch - could you take a look? |
| cmake .. | ||
| make -j | ||
|
|
||
| [ -f ssl/libssl.a ] || { echo "Failed to build libssl.a" ; exit 1 ; } |
There was a problem hiding this comment.
please add a note where this magic is coming from. Without more context, this seems very arbitrary and hacky.
There was a problem hiding this comment.
What magic do you mean? Do you mean the path where libssl.a is in?
There was a problem hiding this comment.
sorry for not being clearer. by "magic" I meant the sequence of commands (build, call read_symbols.go, build again, ...) that someone without context will have no idea where they came from. If you just mention you got the commands from the boringssl docs for prefixing symbols then all is fine I think.
|
|
||
| # generates boringssl_prefix_symbols.h | ||
| cmake .. -DBORINGSSL_PREFIX=GRPC -DBORINGSSL_PREFIX_SYMBOLS=symbols.txt | ||
| make boringssl_prefix_symbols |
There was a problem hiding this comment.
does boringssl provide the make boringssl_prefix_symbols? please link to boringssl docs if this is documented somewhere.
There was a problem hiding this comment.
Looks like this is based on https://github.com/google/boringssl/blob/master/BUILDING.md#building-with-prefixed-symbols
please do include this link as explanation of what's happening.
| import subprocess | ||
| boringssl_commit = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd='third_party/boringssl-with-bazel').decode().strip() | ||
|
|
||
| import gzip, shutil, os, base64 |
There was a problem hiding this comment.
please include some explanation of what's the point of this snippet (I see there's some explanation below, but without more context it's not really clear that this snippet is related to that).
| # We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists | ||
| find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include <openssl/;#include <openssl_grpc/;g' | ||
| END_OF_COMMAND | ||
| # BoringSSL include boringssl_prefix_symbols.h without any prefix, which does not match the |
There was a problem hiding this comment.
This line has an unfinished sentence, probably a typo?
| # /src/boringssl/boringssl_prefix_symbols.h. Here we decode the content and inject the header to | ||
| # the correct location in BoringSSL. | ||
| base64 -D <<EOF | gunzip > src/include/openssl/boringssl_prefix_symbols.h | ||
| ${prefix_gz_b64} |
There was a problem hiding this comment.
nit: instead of using a "global" variable in the prologue, would it be more readable to actually define a function and then invoke it from here?
| # /src/boringssl/boringssl_prefix_symbols.h. Here we decode the content and inject the header to | ||
| # the correct location in BoringSSL. | ||
| base64 -D <<EOF | gunzip > src/include/openssl/boringssl_prefix_symbols.h | ||
| ${prefix_gz_b64} |
There was a problem hiding this comment.
nit: I looked at the generated file and it looks like it generates one extremely long line with base64.
It would be nicer if you wrapped the base64 string at 80 characters, which should still be parseable by the base64 command, but the generated file would look that ugly?
| ss.dependency '${abseil_spec}', abseil_version | ||
| % endfor | ||
| ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS' | ||
| ss.compiler_flags = '-DBORINGSSL_PREFIX=GRPC' |
There was a problem hiding this comment.
qq: have you checked that the symbols are actually getting prefixed when you build like this? I don't see the boringssl_prefix_symbols.h being used anywhere in our build files so I'm just wondering what the trick is. Perhaps boringssl_prefix_symbols.h is being included by boringssl headers, which makes it transparent for grpc usage of boringssl?
There was a problem hiding this comment.
Yes I did check the symbols are prefixed, and correctly used by gRPC. The boringssl_prefix_symbols.h is used in BoringSSL headers. We just need to define the BORINGSSL_PREFIX macro when building gRPC-Core and BoringSSL-GRPC.
jtattermusch
left a comment
There was a problem hiding this comment.
Very nice, thanks for addressing all the comments. LGTM.
|
That's great, thank you very much! |
|
Thank you Jan. |
|
@muxi In this modification, the tag version of Boring-GRPC that gPRC-core depends on has been upgraded to 0.0.8, but the latest version of Boring-GRPC in the cocoapods spec is 0.0.7. May I ask when the Boring-GRPC in the cocoapods spec will be upgraded to 0.0.8? |
|
It will be pushed to Cocoapods trunk with the next gRPC pre-release (v1.29.0-pre1). The release for v1.29.x has been blocked due to some bugs in other gRPC languages, so I cannot tell exactly when it will happen. |
|
Ok, thank you for your answer. |
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free. This patch essentially does what has already been done for cocoapods ( see grpc#21194 ).
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free. This patch essentially does what has already been done for cocoapods ( see #21194 ).
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free. This patch essentially does what has already been done for cocoapods ( see grpc#21194 ).
Prefix BoringSSL APIs with _GRPC_ by default on iOS, by actually isolating it against other libraries with might include openssl themselves and therefore allowing to embed gRPC on iOS completely mind free. This patch essentially does what has already been done for cocoapods ( see grpc#21194 ).
The original approach was a custom script generating the headers, then inject the redefined symbols to both gRPC core and BoringSSL.
The new approach in this PR is to generate symbol prefix header script that BoringSSL provides, in Docker. The prefix header is then manually uploaded to GCS. Users download it when installing BoringSSL-GRPC podspec.
In gRPC-Core and BoringSSL-GRPC Xcode projects, the macro
BORINGSSL_PREFIX=GRPCis defined to prefix all BoringSSL symbols. The macro is provided by BoringSSL, so should be a better solution than our own prefix header.Fixes #22249, #20379
cc: @stanley-cheung