Skip to content

Commit

Permalink
crit(proto-gen): move to Python script
Browse files Browse the repository at this point in the history
Previously, CRIT was using an overengineered Makefile stunt to generate
protobuf bindings for the CLI. The problem of statically linking all the
bindings while using the library as a dependency cannot be resolved in a
reasonable manner in the Makefile. The logic has been moved out into a
Python script.

Signed-off-by: Prajwal S N <prajwalnadig21@gmail.com>
  • Loading branch information
snprajwal committed Apr 4, 2023
1 parent 726559a commit 7a3d779
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
15 changes: 14 additions & 1 deletion scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,20 @@ CRIU uses a 32-bit integer value to determine the type of image file. These valu

`Usage: magicgen.go /path/to/magic.h /path/to/magic.go`

A set of Makefile targets are provided for convenience:
Makefile targets provided:

- `make` or `make magic-gen`: Generate `../magic/magic.go`
- `make test`: Run unit test and E2E test for `magicgen.go`
- `make clean`: Remove `../magic/magic.go` and `magic.h`

## `proto-gen`
CRIT uses protobuf bindings to serialise and deserialise CRIU image files. The definitions for these bindings are available in [criu/images](https://github.com/checkpoint-restore/criu/tree/master/images). `protogen.py` fetches these definitions and generates the `.pb.go` files used by CRIT. If the source or destination directory is not provided, the script uses `../crit/images` by default.

`Usage: protogen.py /path/to/definitions/dir /path/to/destination/dir`

Makefile targets provided:

- `make` or `make pb-gen`: Generate the `.pb.go` bindings
- `make proto-update`: Update the `.proto` files with the latest copy from the CRIU repo. The GIT_BRANCH variable can be used to specify the branch to fetch the files from.
- `make clean-proto`: Delete all `.proto` bindings
- `make clean-pb`: Delete all `.pb.go` bindings
30 changes: 30 additions & 0 deletions scripts/proto-gen/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
PY ?= python3
PROTO_PATH ?= ../../crit/images
PB_PATH ?= ../../crit/images
GIT_BRANCH ?= master

pb-gen: clean-pb
@$(PY) protogen.py $(PROTO_PATH) $(PB_PATH)

proto-update: clean-proto
git clone --depth 1 --branch $(GIT_BRANCH) https://github.com/checkpoint-restore/criu criu-temp
cp criu-temp/images/*.proto $(PROTO_PATH)/
# rpc.proto is not an image and it is used only to communicate criu-service and swrk.
rm -rf criu-temp $(PROTO_PATH)/rpc.proto
# To prevent namespace conflict with proto files
# in github.com/letsencrypt/boulder, we prepend
# a prefix to the filenames.
mv $(PROTO_PATH)/sa.proto $(PROTO_PATH)/criu-sa.proto
sed -i 's/sa\.proto/criu-sa\.proto/g' $(PROTO_PATH)/*.proto
mv $(PROTO_PATH)/core.proto $(PROTO_PATH)/criu-core.proto
sed -i 's/core\.proto/criu-core\.proto/g' $(PROTO_PATH)/*.proto

clean-proto:
@echo "Removing existing .proto files..."
rm $(PROTO_PATH)/*.proto || true

clean-pb:
@echo "Removing existing .pb.go files..."
find $(PB_PATH) -type f -name '*.pb.go' -delete

.PHONY: pb-gen proto-update clean-proto clean-pb
45 changes: 45 additions & 0 deletions scripts/proto-gen/protogen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import os
import shutil
import argparse
import subprocess

parser = argparse.ArgumentParser(
description='A script to generate Go bindings for the protobuf definitions provided by CRIU')
parser.add_argument(
'src', help='Path to the definitions directory', type=str)
parser.add_argument(
'dest', help='Path to the destination directory', type=str)

args = parser.parse_args()

# The import paths for each package passed to --go_opt
pkg_opts = ''
# The names of the .proto files without the extension
names = []

# Loop over the files in the src dir
for file in os.listdir(args.src):
if file.endswith('.proto'):
# Strip the .proto extension
name = os.path.splitext(file)[0]
names.append(name)
# Add the import path for the protoc file
pkg_opts += ',M{0}.proto=github.com/checkpoint-restore/go-criu/v6/crit/images/{0}'.format(
name)

# Create the dest dir
if not os.path.exists(args.dest):
os.makedirs(args.dest)
# Generate the .pb.go files
command = 'protoc -I {} --go_opt=paths=source_relative{} --go_out={} {}'.format(
args.src, pkg_opts, args.dest, ' '.join(map(lambda s: os.path.join(args.src, s + '.proto'), names)))
result = subprocess.run(command, shell=True)

# Move the files to the respective dirs
for name in names:
# Create dir with the same name as the file
dir_name = os.path.join(args.dest, name)
os.makedirs(dir_name, exist_ok=True)
# Move the generated .pb.go file from the dest dir
shutil.move(os.path.join(args.dest, name + '.pb.go'),
os.path.join(dir_name, name + '.pb.go'))

0 comments on commit 7a3d779

Please sign in to comment.