C++

macOS下编译C++文件

WebAssembly 是一种新的编译目标,可以将 C/C++ 等语言编译成 WebAssembly,然后在浏览器中运行。我最近在研究如何把zbar (opens new window)编译成 WebAssembly,然后在浏览器中使用。第一步就是想把官方的例子编译成二进制测试下代码,但是在 MacOS 下编译的时候遇到了一些问题,这里记录下。

# 官方例子

scan_image.cpp (opens new window)

官方提供了一个例子,可以用来测试二维码识别功能,这个例子有两个依赖 Magick++.h 和 zbar.h,这两个库都可以通过 brew 安装。

brew install imagemagick
brew install zbar
1
2

因为从源码编译对我来说实在是太复杂了,所以我就选择了直接安装相关依赖。

# 编译

g++ -o scan_image scan_image.cpp
1

执行上面的命令,会报错:

scan_image.cpp:1:10: fatal error: 'Magick++.h' file not found
1

这是因为 Magick++.h 的头文件在 /opt/homebrew/include/ImageMagick-7/Magick++.h,但是 g++ 默认只会在 /opt/homebrew/include 目录下查找头文件,所以我们需要指定头文件的路径。

g++ -o scan_image scan_image.cpp -I/opt/homebrew/include/ImageMagick-7
1

执行上面的命令还是会有报错:

/opt/homebrew/include/ImageMagick-7/MagickCore/magick-config.h:63:3: warning: "you should set MAGICKCORE_QUANTUM_DEPTH to sensible default set it to configure time default" [-W#warnings]
# warning "you should set MAGICKCORE_QUANTUM_DEPTH to sensible default set it to configure time default"
  ^
/opt/homebrew/include/ImageMagick-7/MagickCore/magick-config.h:64:3: warning: "this is an obsolete behavior please fix your makefile" [-W#warnings]
# warning "this is an obsolete behavior please fix your makefile"
  ^
/opt/homebrew/include/ImageMagick-7/MagickCore/magick-config.h:86:3: error: "you should set MAGICKCORE_HDRI_ENABLE"
# error "you should set MAGICKCORE_HDRI_ENABLE"
  ^
/opt/homebrew/include/ImageMagick-7/MagickCore/magick-config.h:121:3: error: "you should set MAGICKCORE_HDRI_ENABLE"
# error "you should set MAGICKCORE_HDRI_ENABLE"
1
2
3
4
5
6
7
8
9
10
11

我们需要设置两个 ImageMagick 需要的编译变量:

g++ -o scan_image scan_image.cpp -I/opt/homebrew/include/ImageMagick-7 -DMAGICKCORE_QUANTUM_DEPTH=16 -DMAGICKCORE_HDRI_ENABLE=0
1

设置了这两个变量之后,还是会报错:

Undefined symbols for architecture arm64:
  "Magick::Blob::Blob()", referenced from:
      _main in scan_image-727bdc.o
  "_zbar_get_symbol_name", referenced from:
      zbar::Symbol::get_type_name() const in scan_image-727bdc.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
1
2
3
4
5
6
7

这是因为我们只引用了头文件,却没有引用相关库的实现。我们需要指定 ImageMagick 的库文件路径,这里我使用的是 brew 安装的 ImageMagick,所以库文件在 /opt/homebrew/lib/ImageMagick 目录下。

g++ -o scan_image scan_image.cpp -I/opt/homebrew/include/ImageMagick-7 -L/opt/homebrew/lib/ImageMagick -DMAGICKCORE_QUANTUM_DEPTH=16 -DMAGICKCORE_HDRI_ENABLE=0 -lMagick++-7.Q16HDRI -lzbar
1

同时我们需要使用 -l 参数来指定需要链接的库,这里需要链接 Magick++-7.Q16HDRI 和 zbar。

# CMake

上面的编译命令比较长,而且如果我们需要编译多个文件的时候,就需要写很多次,所以我们可以使用 CMake 来简化编译过程。

cmake_minimum_required(VERSION 3.10)
project(ScanImage)


set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=16")

include_directories(/opt/homebrew/include/ImageMagick-7)
link_directories(/opt/homebrew/lib/ImageMagick)

add_executable(ScanImage scan_image.cpp)
target_link_libraries(ScanImage zbar Magick++-7.Q16HDRI)
1
2
3
4
5
6
7
8
9
10
11
12

# 总结

C++ 的编译报错总是让人摸不着头脑,这里我只是简单的记录了下我遇到的问题和解决方案,希望能帮助到大家。

# 参考

how to #include third party libraries (opens new window)

zbar-wasm (opens new window)

Mac M1系统配置C++环境

最近在学习计算机图形学,需要配置C++环境和opencv来编译作业代码,于是我就开始折腾下M1如何编译C++代码了。

# 安装依赖

首先你需要安装Mac下的包管理器 homebrew (opens new window),官网有详细的安装教程,我就不赘述了。

接下来安装C++相关的依赖:

brew install gcc cmake
1

然后是图形学相关的依赖:

brew install eigen opencv
1

# 配置头文件路径

This script installs Homebrew to its preferred prefix (/usr/local for macOS Intel, /opt/homebrew for Apple Silicon and /home/linuxbrew/.linuxbrew for Linux) so that you don’t need sudo when you brew install.

homebrew 官网有描述M1的安装路径更改到 /opt/homebrew 了。所以我们需要指定头文件路径,这里我们指定到 /opt/homebrew/include

export CPATH=/opt/homebrew/include
export LIBRARY_PATH=/opt/homebrew/lib
1
2

把上述代码添加到 .bashrc 文件,如果你使用的是 zsh 请添加到 .zshrc 文件。

# 检测头文件路径

gcc -x c++ -v -E /dev/null 
1

如果输出结果有 /opt/homebrew/include 就说明配置成功了。

# 总结

配置环境看似简单,但找到解决方案需要花不少时间,这里主要问题是M1下安装路径不同,所以我们需要指定头文件路径。

# 参考

Installing a C/C++ library with homebrew on M1 Macs (opens new window)

在 Mac OS 下配置 GAMES101 开发环境 (opens new window)

View default include path of C headers in Mac OS X by gcc -v? (opens new window)