一份适用于 Pylon5 工业相机的 CMakeLists.txt

Pylon5 自带的例子使用 Makefile。但是,CLion 默认建立的项目是 CMake 的。为了能在 CLion 下写代码,我们必须将原有的 Makefile 转成 CMakeList。

但是,Google 告诉我,并没有工具能自动完成这件事…… 那好,一点一点自己来吧。

我们以 Pylon5 自带例子中 C++/Grab 为例,将 Makefile“翻译” 成 CMakeLists.txt。

原有的 Makefile

# Makefile for Basler pylon sample program
.PHONY: all clean

# The program to build
NAME       := Grab

# Installation directories for pylon
PYLON_ROOT ?= /opt/pylon5

# Build tools and flags
LD         := $(CXX)
CPPFLAGS   := $(shell $(PYLON_ROOT)/bin/pylon-config --cflags)
CXXFLAGS   := #e.g., CXXFLAGS=-g -O0 for debugging
LDFLAGS    := $(shell $(PYLON_ROOT)/bin/pylon-config --libs-rpath)
LDLIBS     := $(shell $(PYLON_ROOT)/bin/pylon-config --libs)

# Rules for building
all: $(NAME)

$(NAME): $(NAME).o
    $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)

$(NAME).o: $(NAME).cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

clean:
    $(RM) $(NAME).o $(NAME)

翻译

前几行看起来无关紧要。那么就从 PYLON_ROOT ?= /opt/pylon5 这一行开始。看起来像是个赋值语句,并且下面也用到了 $(PYLON_ROOT) 这样的写法。那么,我们把这句话翻译成 set(PYLON_ROOT "/opt/pylon5")

下面,LD:= $(CXX)。直接在 shell 里面输入 echo $(CXX) 并没有什么东西,就直接忽略了。感觉这句话只是 “取个别名” 而已。

再下面,重点来了。CPPFLAGS := $(shell $(PYLON_ROOT)/bin/pylon-config --cflags) 这句话,明显的是执行一个 shell 语句,获得执行结果,再赋值。Google 了好久,最终得到以下结果:

EXEC_PROGRAM("${PYLON_ROOT}/bin/pylon-config" ARGS --cflags OUTPUT_VARIABLE CPPFLAGS)
SET(CPPFLAGS "${CPPFLAGS}" CACHE STRING "CPPFLAGS")

而且,Makefile 里面的 CPPFLAGS 好像是对应 CMakeLists 里面的 CMAKE_C_FLAGS 的。那么,下面再加一句

SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CPPFLAGS}")

这里就会有人问了,下面这样写,不行么?

EXEC_PROGRAM("${PYLON_ROOT}/bin/pylon-config" ARGS --cflags OUTPUT_VARIABLE CPPFLAGS)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CPPFLAGS}" CACHE STRING "CPPFLAGS")

还真不行。原因未知。

如法炮制余下的 LDFLAGSLDLIBSLDFLAGS 对应的是 CMAKE_EXE_LINKER_FLAGSLDLIBS 需要写在 target_link_libraries 里。

结果

cmake_minimum_required(VERSION 3.6)
project(camera)

find_package(OpenCV REQUIRED)

set(PYLON_ROOT "/opt/pylon5")

include_directories("${PROJECT_BINARY_DIR}")
include_directories("${PYLON_ROOT}/include")

EXEC_PROGRAM("${PYLON_ROOT}/bin/pylon-config" ARGS --cflags OUTPUT_VARIABLE CPPFLAGS)
#SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CPPFLAGS}" CACHE STRING "CPPFLAGS")
SET(CPPFLAGS "${CPPFLAGS}" CACHE STRING "CPPFLAGS")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CPPFLAGS}")

EXEC_PROGRAM("${PYLON_ROOT}/bin/pylon-config" ARGS --libs-rpath OUTPUT_VARIABLE LDFLAGS)
#SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LDFLAGS}" CACHE STRING "LDFLAGS")
SET(LDFLAGS "${LDFLAGS}" CACHE STRING "LDFLAGS")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LDFLAGS}")

EXEC_PROGRAM("${PYLON_ROOT}/bin/pylon-config" ARGS --libs OUTPUT_VARIABLE LDLIBS)
SET(LDLIBS "${LDLIBS}" CACHE STRING "LDLIBS")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")

set(SOURCE_FILES main.cpp)

add_executable(camera ${SOURCE_FILES})
target_link_libraries(camera ${OpenCV_LIBS} ${LDLIBS})

结束

Grab.cpp 一字不差抄过来,编译,成功。

转译得好像不是特别简洁,但是能用。这就行了。

至于为什么参数是 -std=c++14…… 因为 Bjarne Stroustrup 老爷子昨天来学校演讲说,要用新标准,要用新标准……“你一个字都不用改动,使用新标准进行编译,就能获得巨大的性能提升”。就相信你一次喽~

参考资料

留下评论