Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting the filename used in the protoc command #437

Merged
32 changes: 27 additions & 5 deletions asdf.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ to PARENT-PATH."
(resolve-relative-pathname path parent-path))
search-path))))

(defun get-search-paths (protobuf-source-file)
"For a given PROTOBUF-SOURCE-FILE, generate the search paths that should be used.
To do this, it creates a search path from the component, as well as the
:proto-search-path specified in the asd component.

If there's a :proto-pathname specified in the component, the generated search
path will be the absolute directory of the :proto-pathname.
If there's not a :proto-pathname specified in the component, the generated
search path will be the directory of the parent component."
(cons
(if (proto-pathname protobuf-source-file)
;; If there's a pathname specified, use the absolute directory of the pathname.
(directory-namestring (proto-input protobuf-source-file))
;; If there's no pathname, use the directory of the parent component.
(asdf/component:component-parent-pathname protobuf-source-file))
;; Attach the other search paths on the back
(resolve-search-path protobuf-source-file)))

(define-condition protobuf-compile-failed (compile-failed-error)
()
(:documentation "Condition signalled when translating a .proto file into Lisp code fails."))
Expand All @@ -117,25 +135,29 @@ to PARENT-PATH."

(defmethod perform ((operation proto-to-lisp) (component protobuf-source-file))
(let* ((source-file (first (input-files operation component)))
(source-file-argument (if *protoc-relative-path*
(source-file-argument (if (proto-pathname component)
;; If a PROTO-PATHNAME is specified in the component, use only the
;; filename and type as the argument to protoc.
(file-namestring source-file)
;; If a PROTO-PATHNAME is not specified in the component, use the
;; entire PROTOBUF-SOURCE-FILE + .proto as the argument to protoc.
(namestring source-file)))
;; Around methods on output-file may globally redirect output products, so we must call
;; that method instead of executing (component-pathname component).
(output-file (first (output-files operation component)))
(search-path (cons (directory-namestring source-file) (resolve-search-path component)))
(search-path (get-search-paths component))
(command (format nil "protoc --proto_path=~{~A~^:~} --cl-pb_out=output-file=~A:~A ~A ~
--experimental_allow_proto3_optional"
search-path
(file-namestring output-file)
(directory-namestring output-file)
source-file-argument)))
(multiple-value-bind (output error-output status)
(uiop:run-program command :output t :error-output :output :ignore-error-status t)
(declare (ignore output error-output))
(uiop:run-program command :output '(:string :stripped t) :error-output :output :ignore-error-status t)
(declare (ignore error-output))
(unless (zerop status)
(error 'protobuf-compile-failed
:description (format nil "Failed to compile proto file. Command: ~S" command)
:description (format nil "Failed to compile proto file. Command: ~S Error: ~S" command output)
:context-format "~/asdf-action::format-action/"
:context-arguments `((,operation . ,component)))))))

Expand Down
13 changes: 12 additions & 1 deletion cl-protobufs.asd
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ and functionality for working with them."
:depends-on ("models" "parsing" "schema" "serialization")
:components
((:file "message-api")))
;; TODO(michaeldelago) Update well-known types to use their full path (ie google/protobuf/descriptor).
(:module "well-known-types"
:serial t
:pathname ""
Expand Down Expand Up @@ -337,6 +338,16 @@ and functionality for working with them."
:serial t
:pathname ""
:depends-on ("root-suite" "google-tests-proto")
:components ((:file "message-api-test"))))
:components ((:file "message-api-test")))
(:module "deep-import"
:serial t
:pathname ""
:components ((:protobuf-source-file "deep-import-test-1")
(:protobuf-source-file "deep-import/deep-import-test-2")
(:protobuf-source-file "deep-import-test-3"
:proto-pathname "deep-import/deep-import-test-3.proto")
(:protobuf-source-file "deep-import-proto"
:proto-search-path ("deep-import/"))
(:file "deep-import-test"))))
:perform (test-op (o c)
(uiop:symbol-call '#:cl-protobufs.test '#:run-all)))
19 changes: 19 additions & 0 deletions tests/deep-import-proto.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

syntax = "proto2";

package third_party.lisp.cl_protobufs.tests;

import "deep-import-test-1.proto"; // Test proto
import "deep-import/deep-import-test-2.proto"; // Test proto
import "deep-import-test-3.proto"; // Test proto

message DeepImportTest {
optional DeepImport1 import1 = 1;
optional DeepImport2 import2 = 2;
optional DeepImport3 import3 = 3;
}
12 changes: 12 additions & 0 deletions tests/deep-import-test-1.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

syntax = "proto2";

package third_party.lisp.cl_protobufs.tests;

message DeepImport1 {
}
56 changes: 56 additions & 0 deletions tests/deep-import-test.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
;;; Copyright 2020 Google LLC
;;;
;;; Use of this source code is governed by an MIT-style
;;; license that can be found in the LICENSE file or at
;;; https://opensource.org/licenses/MIT.

(defpackage #:cl-protobufs.test.deep-import
(:use #:cl
#:clunit)
(:local-nicknames (#:pb #:cl-protobufs.third-party.lisp.cl-protobufs.tests)
(#:pi #:cl-protobufs.implementation))
(:export :run))

(in-package #:cl-protobufs.test.deep-import)


(defsuite deep-import-suite (cl-protobufs.test:root-suite))

(defun run (&key use-debugger)
"Run all tests in the test suite.
Parameters
USE-DEBUGGER: On assert failure bring up the debugger."
(clunit:run-suite 'deep-import-suite :use-debugger use-debugger
:signal-condition-on-fail t))

(deftest test-all-imports-are-included (deep-import-suite)
"Ensure file imports of the parent structure are properly read and stored with its file descriptor."
(let* ((descriptor (cl-protobufs:find-file-descriptor 'pb:deep-import-proto))
(imports (pi::proto-imports descriptor)))
;; Confirms there are in-fact 3 imports on the testing deep-import-proto.
(assert-eql 3 (length imports))
;; This is defined next to the test proto.
(assert-equal "deep-import-test-1.proto" (first imports))
;; this is defined in deep-import as "deep-import/deep-import-test-2".
(assert-equal "deep-import/deep-import-test-2.proto" (second imports))
;; this is defined in deep-import as "deep-import-test-3" with the
;; proto-pathname set relative to the testing directory. deep-import-proto
;; sets a search path in order to find this file.
(assert-equal "deep-import-test-3.proto" (nth 2 imports))))

(deftest test-file-descriptors (deep-import-suite)
"Ensure generated lisp files add their PROTO-SOURCE-FILE to CL-PROTOBUFS.IMPLEMENTATION."
(assert-true
(cl-protobufs:find-file-descriptor #P"deep-import/deep-import-test-2.proto"))
(assert-true
(cl-protobufs:find-file-descriptor #P"deep-import-test-3.proto")))

(deftest test-make-sub-structures (deep-import-suite)
"Ensure imported sub-structure can be made."
(assert-true (pb:make-deep-import1))
(assert-true (pb:make-deep-import2))
(assert-true (pb:make-deep-import3)))

(deftest test-make-structure (deep-import-suite)
"Ensure parent structure can be made."
(assert-true (pb:make-deep-import-test :import1 (pb:make-deep-import1))))
12 changes: 12 additions & 0 deletions tests/deep-import/deep-import-test-2.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

syntax = "proto2";

package third_party.lisp.cl_protobufs.tests;

message DeepImport2 {
}
12 changes: 12 additions & 0 deletions tests/deep-import/deep-import-test-3.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

syntax = "proto2";

package third_party.lisp.cl_protobufs.tests;

message DeepImport3 {
}