// usr / local / include意外添加到我的编译命令中,导致构建失败

问题描述 投票:0回答:3

背景

我正在运行macOS 10.15的计算机上编译一个项目,该项目将旧版本的libpng(1.6.17)作为子模块提供。相应的代码位于https://github.com/glennrp/libpng。我也有Homebrew安装的libpng 1.6.37。

直到不久前,我才能够使用CMake轻松编译libpng 1.6.17。由于最近(但我不知道确切的日期),因此构建失败并显示以下错误:

FAILED: CMakeFiles/png16_static.dir/pngwutil.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc  -I/usr/local/include -I. -I../ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -MD -MT CMakeFiles/png16_static.dir/pngwutil.o -MF CMakeFiles/png16_static.dir/pngwutil.o.d -o CMakeFiles/png16_static.dir/pngwutil.o   -c ../pngwutil.c
../pngwutil.c:2413:20: error: use of undeclared identifier 'PNG_WEIGHT_SHIFT'
                   PNG_WEIGHT_SHIFT;
                   ^

我对我的项目的副本进行了一些检查,该项目的副本仍可正确编译,因为CMake并未在其上重新运行自身。两种情况之间的唯一区别是在编译器调用中添加了-I/usr/local/include标志(我添加了一些标记以帮助查看区别):

  • 成功:
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -Dpng16_EXPORTS -Iext_build/libpng -I../../ext/libpng -O3 -DNDEBUG -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -fPIC   -fno-stack-protector -fomit-frame-pointer -fno-math-errno -ffp-contract=fast -march=native -MD -MT ext_build/libpng/CMakeFiles/png16.dir/pngrio.o -MF ext_build/libpng/CMakeFiles/png16.dir/pngrio.o.d -o ext_build/libpng/CMakeFiles/png16.dir/pngrio.o   -c ../../ext/libpng/pngrio.c
                                                                                             <---------------------------------->
    
  • 失败:
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -Dpng16_EXPORTS -I/usr/local/include -Iext_build/libpng -I../../ext/libpng -O3 -DNDEBUG -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -fPIC   -fno-stack-protector -fomit-frame-pointer -fno-math-errno -ffp-contract=fast -march=native -MD -MT ext_build/libpng/CMakeFiles/png16.dir/pngrio.o -MF ext_build/libpng/CMakeFiles/png16.dir/pngrio.o.d -o ext_build/libpng/CMakeFiles/png16.dir/pngrio.o   -c ../../ext/libpng/pngrio.c
                                                                                             <------------------------------------------------------->
    

我在正在运行的项目副本上重新运行CMake,但遇到了相同的错误,这使我指出了与系统相关的问题。然后,我直接检出了libpng源,并得到了相同的错误。

复制步骤

  1. 克隆libpng仓库并查看v1.6.17
    git clone https://github.com/glennrp/libpng.git
    cd libpng
    git checkout v1.6.17
    
  2. 构建libpng
    cmake . -B build && cmake --build build
    

问题

将此-I/usr/local/include标志添加到我的编译器调用中的原因是什么?

奖金问题(可能更有趣)

现在,它很有趣。如果您签出较新的libpng(我尝试使用1.6.21、1.6.25、1.6.28、1.6.33和1.6.37),则问题会消失,尽管该标志仍然在此处:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc  -I/usr/local/include -I. -I../ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -MD -MT CMakeFiles/png16_static.dir/pngrio.o -MF CMakeFiles/png16_static.dir/pngrio.o.d -o CMakeFiles/png16_static.dir/pngrio.o   -c ../pngrio.c

这意味着我可以使用这些发行版之一来更新子模块,而我的问题将消失。

但是,如果我没记错的话,-I标志是从左到右解析的:因此,我怀疑我使用的Homebrew标头代替了源标头。如果我是对的,那么这不能保证libpng的Homebrew升级不会再次破坏构建:它只是表明libpng的API自v1.6.21以来一直是稳定的,并且我可以将Homebrew标头与源一起使用我正在尝试编译。我是对的还是我错过了什么?

macos cmake clang homebrew libpng
3个回答
1
投票
  1. 问题的答案:系统包含路径是由编译器/预处理器添加的(this page将解释更多数据)
  2. 可能会更改CMake项目中包含的顺序(不确定多少),CMake允许在列表中添加前面的内容;尝试比较两个版本之间的CMake构建脚本。我相信会有提及的变化。

0
投票

是的,有时cmake会拾取各种库,包括dirs,并自由地混合和匹配。如果需要保持多个版本,则应使用cmake命令传递正确的软件包。


0
投票

我终于找到答案了。原来,libpng的zlib依赖关系(间接地)给我带来了麻烦。

发生了什么

MacOS附带了zlib,开发人员通常知道它,因此他们不需要安装第三方zlib。但是,CMake的find_package不了解此首选项,并且会选择/usr/local中的zlib实现,例如,如果它是由Homewbrew安装的。由于某种原因,第3方软件在我的系统上的该位置安装了zlib,而不是Homebrew软件包,这使得检测更加困难,并由find_package进行了检测。

相应的包含目录是/usr/local/include。 libpng的CMake代码是这样的,然后将该目录添加到包含目录的列表中,这会导致问题中提到的标头冲突。我了解通过CMakeCache.txt(搜索/usr/local/include)发生的情况,所以主要的教训是:在这种情况下,请不要忘记检查您的CMake缓存

如何解决问题

懒惰的方式。删除不需要的lib文件。我运行了brew doctor并删除了不应该在这里的文件。但是,如果某些软件实际上需要/usr/local中的特定zlib版本,则可能会产生不希望的结果。

CMake肮脏的方式。修改顶级CMake代码以提示find_package有关应该在哪里选择zlib。您可以使用find_package参数对提示进行硬编码,也可以使用PATHS参数进行设置(您可能需要为此定义策略)。

[我敢肯定,有一种更好的方法可以通过libpng中的ZLIB_ROOT处理并在系统路径中强制执行库搜索,但是我的CMake技能不足以说出应该做什么。而且,相对于该问题而言,它有点偏离主题。

© www.soinside.com 2019 - 2024. All rights reserved.