如何在CMake中实现shell反引号(`)命令替换以适配png++编译?
使用CMake构建png++项目的问题解决
我正在使用png++库,该库要求通过以下Shell命令编译:
g++ -c example.cpp `libpng-config --cflags` g++ -o example example.o `libpng-config --ldflags`
这种方式可以正常工作,但我用CLion开发,希望用CMake规范构建(不想直接运行Shell脚本)。试了两种CMakeLists写法都失败,猜测问题出在反引号(`)上,不清楚它的具体含义。
我尝试的两种CMakeLists写法
写法一
cmake_minimum_required(VERSION 3.27) project(image_proc) set(CMAKE_CXX_STANDARD 17) add_executable(image_proc src/main.cpp src/core.h) add_compile_options(`libpng-config --cflags`) add_link_options(`libpng-config --ldflags`)
写法二
cmake_minimum_required(VERSION 3.27) project(image_proc) set(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} `libpng-config --cflags`") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} `libpng-config --ldflags`") add_executable(image_proc src/main.cpp src/core.h)
错误输出
====================[ Build | image_proc | Debug ]============================== /home/saprykin/.local/share/JetBrains/Toolbox/apps/clion-nova/bin/cmake/linux/x64/bin/cmake --build /home/saprykin/image_proc/cmake-build-debug --target image_proc -j 3 [1/1] Linking CXX executable image_proc FAILED: image_proc : && /usr/bin/c++ -g CMakeFiles/image_proc.dir/src/main.cpp.o -o image_proc && : /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::info_base::info_base(png::io_base&, png_struct_def*)': /usr/local/include/png++/info_base.hpp:55: undefined reference to `png_create_info_struct' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::info::write() const': /usr/local/include/png++/info.hpp:126: undefined reference to `png_set_PLTE' /usr/bin/ld: /usr/local/include/png++/info.hpp:133: undefined reference to `png_set_tRNS' /usr/bin/ld: /usr/local/include/png++/info.hpp:147: undefined reference to `png_set_gAMA' /usr/bin/ld: /usr/local/include/png++/info.hpp:157: undefined reference to `png_write_info' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::info::sync_ihdr() const': /usr/local/include/png++/info.hpp:172: undefined reference to `png_set_IHDR' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::end_info::destroy()': /usr/local/include/png++/end_info.hpp:56: undefined reference to `png_destroy_info_struct' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::end_info::write() const': /usr/local/include/png++/end_info.hpp:66: undefined reference to `png_write_end' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::io_base::set_swap() const': /usr/local/include/png++/io_base.hpp:315: undefined reference to `png_set_swap' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::io_base::set_interlace_handling() const': /usr/local/include/png++/io_base.hpp:379: undefined reference to `png_set_interlace_handling' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::io_base::raise_error()': /usr/local/include/png++/io_base.hpp:449: undefined reference to `png_set_longjmp_fn' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::io_base::raise_error(png_struct_def*, char const*)': /usr/local/include/png++/io_base.hpp:454: undefined reference to `png_get_error_ptr' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::writer<std::basic_ofstream<char, std::char_traits<char> > >::writer(std::basic_ofstream<char, std::char_traits<char> >&)': /usr/local/include/png++/writer.hpp:78: undefined reference to `png_create_write_struct' /usr/bin/ld: /usr/local/include/png++/writer.hpp:80: undefined reference to `png_set_write_fn' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::writer<std::basic_ofstream<char, std::char_traits<char> > >::~writer()': /usr/local/include/png++/writer.hpp:86: undefined reference to `png_destroy_write_struct' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::writer<std::basic_ofstream<char, std::char_traits<char> > >::write_info() const': /usr/local/include/png++/writer.hpp:106: undefined reference to `png_set_longjmp_fn' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::writer<std::basic_ofstream<char, std::char_traits<char> > >::write_row(unsigned char*)': /usr/local/include/png++/writer.hpp:118: undefined reference to `png_set_longjmp_fn' /usr/bin/ld: /usr/local/include/png++/writer.hpp:122: undefined reference to `png_write_row' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::writer<std::basic_ofstream<char, std::char_traits<char> > >::write_end_info() const': /usr/local/include/png++/writer.hpp:130: undefined reference to `png_set_longjmp_fn' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::writer<std::basic_ofstream<char, std::char_traits<char> > >::write_data(png_struct_def*, unsigned char*, unsigned long)': /usr/local/include/png++/writer.hpp:140: undefined reference to `png_get_error_ptr' /usr/bin/ld: /usr/local/include/png++/writer.hpp:143: undefined reference to `png_get_io_ptr' /usr/bin/ld: CMakeFiles/image_proc.dir/src/main.cpp.o: in function `png::writer<std::basic_ofstream<char, std::char_traits<char> > >::flush_data(png_struct_def*)': /usr/local/include/png++/writer.hpp:169: undefined reference to `png_get_error_ptr' /usr/bin/ld: /usr/local/include/png++/writer.hpp:172: undefined reference to `png_get_io_ptr' collect2: error: ld returned 1 exit status ninja: build stopped: subcommand failed.
问题原因及解决方法
反引号的含义
在Shell环境中,反引号`的作用是命令替换:执行反引号内的命令,把命令的输出结果直接替换到当前位置。比如libpng-config --cflags会输出编译png++需要的头文件路径等参数,libpng-config --ldflags会输出链接时需要的库路径和库名。
你的CMake写法错误原因
CMake不识别Shell的反引号语法,直接写add_compile_options(libpng-config --cflags)会把整个字符串libpng-config --cflags当成编译选项,而不是执行该命令获取实际参数,导致编译和链接时没有正确引入libpng的依赖,所以出现大量未定义引用错误。
正确的CMakeLists.txt写法
方法一:使用execute_process获取参数
用CMake的execute_process命令执行libpng-config,获取输出参数后再应用到项目:
cmake_minimum_required(VERSION 3.27) project(image_proc) set(CMAKE_CXX_STANDARD 17) # 获取libpng的编译参数 execute_process( COMMAND libpng-config --cflags OUTPUT_VARIABLE LIBPNG_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ) # 获取libpng的链接参数 execute_process( COMMAND libpng-config --ldflags OUTPUT_VARIABLE LIBPNG_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ) add_executable(image_proc src/main.cpp src/core.h) # 将参数应用到目标 target_compile_options(image_proc PRIVATE ${LIBPNG_CFLAGS}) target_link_options(image_proc PRIVATE ${LIBPNG_LDFLAGS})
方法二:使用pkg_check_modules(更规范)
借助CMake的pkg_check_modules模块,通过pkg-config工具查找libpng的依赖,这种方式更符合现代CMake的用法:
cmake_minimum_required(VERSION 3.27) project(image_proc) set(CMAKE_CXX_STANDARD 17) # 查找pkg-config模块 find_package(PkgConfig REQUIRED) # 通过pkg-config查找libpng pkg_check_modules(LIBPNG REQUIRED libpng) add_executable(image_proc src/main.cpp src/core.h) # 链接libpng的依赖库 target_link_libraries(image_proc PRIVATE ${LIBPNG_LIBRARIES}) # 添加libpng的头文件路径 target_include_directories(image_proc PRIVATE ${LIBPNG_INCLUDE_DIRS}) # 添加libpng的编译选项 target_compile_options(image_proc PRIVATE ${LIBPNG_CFLAGS_OTHER})
两种写法都能正确获取libpng的编译和链接参数,解决链接时的未定义引用问题。
内容的提问来源于stack exchange,提问作者maridj
相关产品推荐
相关产品推荐

