从二进制文件中删除 protobuf c++ 编译的路径字符串
Remove protobuf c++ compiled path string from binary
当我编译使用 Protobuf 的 c++ 程序,然后 运行 对二进制文件执行 linux strings
命令时,其中一个字符串是生成的 cc
文件,包含我的主目录和所有内容。显然我想从二进制文件中删除我的主目录和其他个人信息。
这个路径是从哪里来的,我怎样才能防止它进入编译后的二进制文件?
字符串来自内嵌的protobuf描述符,用于对protobuf类型进行动态自省。本质上,描述符描述了整个 .proto
文件。描述符本身以 protobuf 格式编码;参见 google/protobuf/descriptor.proto。
现在,描述符通常应该不包含您所描述的绝对路径。它确实想要包含 "canonical" 路径——也就是说,proto 文件相对于源代码根目录的路径名,或者换句话说,你在 import
语句中编写的路径对于那个文件。例如,descriptor.proto
自己的规范路径是 google/protobuf/descirptor.proto
;要导入它,您可以写 import "google/protobuf/descriptor.proto";
.
您的描述符获得完整绝对文件系统路径的原因是因为这是您传递给 protoc
的路径,并且您没有传递 -I
标志来告诉 protoc
源代码树的根所在的位置。由于protoc
无法找出源代码的root,所以正在回退到文件系统root。
例如,假设您的 .proto
文件是 /home/foo/myproj/src/frobber/baz.proto
。说这个路径下的src
目录是你的"source root",意思是你要人家写import "frobber/baz.proto";
导入你的proto文件。在这种情况下,您希望像这样调用 protoc
:
protoc -I/home/foo/myproj/src /home/foo/myproj/src/frobber/baz.proto
请注意,如果您是 运行 来自 myproj
目录的命令,那么您可能根本不应该指定绝对路径:
protoc -Isrc src/frobber/baz.proto
这里的-I
标志是源文件名的文本前缀,这一点很重要。 protoc
很笨,只知道比较字符串。例如,它不知道当前目录是什么:
# DOES NOT WORK
cd /home/foo/myproj
protoc -I/home/foo/myproj/src src/frobber/baz.proto
而且它也不能规范化“..”:
# DOES NOT WORK: protoc doesn't collapse "xyz/../".
protoc -Isrc xyz/../src/frobber/baz.proto
然而,“..”如果一致就可以,因为再次 protoc
只关心前缀匹配:
# OK: Prefix is consistent.
protoc -Ixyz/../src xyz/../src/frobber/baz.proto
如果您不想使用描述符
您可以通过在 .proto
文件中放置以下行来编译 "lite mode" 中的原型文件:
option optimize_for = LITE_RUNTIME;
在此模式下,将完全不包含描述符。此外,您可以 link 对抗 "lite" 版本的 protobuf 运行时库,它比常规版本小得多。但是,许多有用的功能将被禁用。整个反射界面将消失,任何依赖于反射的东西也将消失。例如,TextFormat
,这是 DebugString()
方法用于将消息转换为文本以打印以进行调试的方法,将被删除,因此调试将更加困难。
当我编译使用 Protobuf 的 c++ 程序,然后 运行 对二进制文件执行 linux strings
命令时,其中一个字符串是生成的 cc
文件,包含我的主目录和所有内容。显然我想从二进制文件中删除我的主目录和其他个人信息。
这个路径是从哪里来的,我怎样才能防止它进入编译后的二进制文件?
字符串来自内嵌的protobuf描述符,用于对protobuf类型进行动态自省。本质上,描述符描述了整个 .proto
文件。描述符本身以 protobuf 格式编码;参见 google/protobuf/descriptor.proto。
现在,描述符通常应该不包含您所描述的绝对路径。它确实想要包含 "canonical" 路径——也就是说,proto 文件相对于源代码根目录的路径名,或者换句话说,你在 import
语句中编写的路径对于那个文件。例如,descriptor.proto
自己的规范路径是 google/protobuf/descirptor.proto
;要导入它,您可以写 import "google/protobuf/descriptor.proto";
.
您的描述符获得完整绝对文件系统路径的原因是因为这是您传递给 protoc
的路径,并且您没有传递 -I
标志来告诉 protoc
源代码树的根所在的位置。由于protoc
无法找出源代码的root,所以正在回退到文件系统root。
例如,假设您的 .proto
文件是 /home/foo/myproj/src/frobber/baz.proto
。说这个路径下的src
目录是你的"source root",意思是你要人家写import "frobber/baz.proto";
导入你的proto文件。在这种情况下,您希望像这样调用 protoc
:
protoc -I/home/foo/myproj/src /home/foo/myproj/src/frobber/baz.proto
请注意,如果您是 运行 来自 myproj
目录的命令,那么您可能根本不应该指定绝对路径:
protoc -Isrc src/frobber/baz.proto
这里的-I
标志是源文件名的文本前缀,这一点很重要。 protoc
很笨,只知道比较字符串。例如,它不知道当前目录是什么:
# DOES NOT WORK
cd /home/foo/myproj
protoc -I/home/foo/myproj/src src/frobber/baz.proto
而且它也不能规范化“..”:
# DOES NOT WORK: protoc doesn't collapse "xyz/../".
protoc -Isrc xyz/../src/frobber/baz.proto
然而,“..”如果一致就可以,因为再次 protoc
只关心前缀匹配:
# OK: Prefix is consistent.
protoc -Ixyz/../src xyz/../src/frobber/baz.proto
如果您不想使用描述符
您可以通过在 .proto
文件中放置以下行来编译 "lite mode" 中的原型文件:
option optimize_for = LITE_RUNTIME;
在此模式下,将完全不包含描述符。此外,您可以 link 对抗 "lite" 版本的 protobuf 运行时库,它比常规版本小得多。但是,许多有用的功能将被禁用。整个反射界面将消失,任何依赖于反射的东西也将消失。例如,TextFormat
,这是 DebugString()
方法用于将消息转换为文本以打印以进行调试的方法,将被删除,因此调试将更加困难。