google/protobuf中一段CMake脚本的含义及写法合理性咨询
作为CMake新手,我在google/protobuf的CMakeLists里看到这段代码:
if (BUILD_SHARED_LIBS) set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON) else (BUILD_SHARED_LIBS) set(protobuf_BUILD_SHARED_LIBS_DEFAULT OFF) endif (BUILD_SHARED_LIBS) option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" ${protobuf_BUILD_SHARED_LIBS_DEFAULT})
我感觉else分支好像毫无意义,想请教这么写的原因是什么?
嘿,这个问题问得特别好!乍一看确实有点多余,但这段代码其实是在处理CMake全局设置和项目自定义设置之间的衔接,背后藏着几个关键的设计考量:
尊重全局构建的默认行为:
BUILD_SHARED_LIBS是CMake的全局选项,当用户配置整个构建树时(比如执行cmake -DBUILD_SHARED_LIBS=ON ..),这个选项会影响所有支持它的子项目。这段代码的核心作用是让protobuf的protobuf_BUILD_SHARED_LIBS默认值和全局的BUILD_SHARED_LIBS保持同步——全局开了共享库编译,protobuf默认也跟着开;全局没开,默认就关闭。保留项目级自定义的灵活性:通过把全局设置映射到项目专属的
protobuf_BUILD_SHARED_LIBS选项,用户依然可以单独覆盖protobuf的编译行为。比如即使全局BUILD_SHARED_LIBS=ON,用户也能通过cmake -Dprotobuf_BUILD_SHARED_LIBS=OFF ..强制让protobuf编译静态库,反过来也成立。代码的可读性与明确性:虽然从逻辑上看,
else分支设置的OFF好像是CMake变量的默认值,但这么写能让阅读代码的人一眼就看明白:protobuf_BUILD_SHARED_LIBS_DEFAULT的取值完全依赖于全局BUILD_SHARED_LIBS的状态,没有任何隐含的默认规则。如果直接写成option(protobuf_BUILD_SHARED_LIBS "..." ${BUILD_SHARED_LIBS})其实也能实现类似效果,但用中间变量加显式判断的方式,更清晰地传递了“我们基于全局设置推导项目默认值”的意图,对新手也更友好。
简单总结一下,这段代码是在全局构建一致性和项目独立定制性之间做了一个优雅的平衡,既跟着全局配置走,又给用户留足了单独调整的空间,同时代码逻辑也更直白易懂。
内容的提问来源于stack exchange,提问作者Li.Cao

