Last week, I shared how to create a CMake project for Windows. Since CMake is a cross-platform software building tool, I am going to make my C/C++ project support Linux and macOS.
Download
- Dynamsoft Barcode Reader 5.2 for Linux
- Dynamsoft Barcode Reader 5.2 for macOS
- CMake for macOS:
brew install cmake
- CMake for Linux:
sudo apt-get install cmake
In contrast to the C/C++ sample code for Windows, the code for Linux and macOS is a little bit different. My goal is to merge them into one .cxx file.
How to Make C/C++ Code Compatible with Multiple Platforms
I used the predefined macros to detect the operating system and customize relevant C/C++ code. Insert the following definitions to BarcodeReaderConfig.h.in:
#if defined(__linux) || defined(__linux__) || defined(linux) # define LINUX #elif defined(__APPLE__) # define MACOS #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(_WIN64) # define WINDOWS #endif
Use macros to control code logic in BarcodeReader.cxx.
How to Configure CMake Project
Windows
In my previous article, I didn’t mention how to select a generator. By default, CMake generates an x86 project in which I couldn’t link DynamsoftBarcodeReaderx64.dll. Let’s list the available generators on Windows:
cmake –help
According to the help information, we can specify a generator with Win64 architecture:
cmake -G"Visual Studio 14 2015 Win64" ..
Link the x64 library in CMakeLists.txt:
if(CMAKE_CL_64) target_link_libraries (BarcodeReader "DBRx64") else() target_link_libraries (BarcodeReader "DBRx86") endif() if(CMAKE_CL_64) add_custom_command(TARGET BarcodeReader POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/platforms/win/DynamsoftBarcodeReaderx64.dll" $<TARGET_FILE_DIR:BarcodeReader>) else() add_custom_command(TARGET BarcodeReader POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/platforms/win/DynamsoftBarcodeReaderx86.dll" $<TARGET_FILE_DIR:BarcodeReader>) endif() if(CMAKE_CL_64) install (FILES "${PROJECT_SOURCE_DIR}/platforms/win/DynamsoftBarcodeReaderx64.dll" DESTINATION bin) else() install (FILES "${PROJECT_SOURCE_DIR}/platforms/win/DynamsoftBarcodeReaderx86.dll" DESTINATION bin) endif()
Linux & macOS
Set the library search path:
if(LINUX) link_directories("${PROJECT_SOURCE_DIR}/platforms/linux") elseif(MACOS) link_directories("${PROJECT_SOURCE_DIR}/platforms/macos") endif()
Link shared libraries:
target_link_libraries (BarcodeReader "DynamsoftBarcodeReader")
Set install destination:
if(LINUX) install (FILES "${PROJECT_SOURCE_DIR}/platforms/linux/libDynamsoftBarcodeReader.so" DESTINATION lib) elseif(MACOS) install (FILES "${PROJECT_SOURCE_DIR}/platforms/macos/libDynamsoftBarcodeReader.dylib" DESTINATION lib) endif()
Build and install the executable file and library:
# Linux sudo cmake --build . --target install # macOS cmake --build . --target install
Note: the default destinations are /usr/local/bin and /usr/local/lib. When you run the executable BarcodeReader, you will see the error message:
libDynamsoftBarcodeReader.so: cannot open shared object file: No such file or directory.
Can we fix the issue by changing the value of CMAKE_INSTALL_PREFIX to ‘/usr/lib’?
set(CMAKE_INSTALL_PREFIX "/usr")
It is okay for Linux, but not permitted on the latest version of macOS.
A usual solution is to export LD_LIBRARY_PATH:
export LD_LIBRARY_PATH =/usr/local/lib: $LD_LIBRARY_PATH
CMake provides a better way that changes RPATH.
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
Build and install the project again. We can now run barcode reader app with no errors.
Source Code
https://github.com/dynamsoft-dbr/cmake
The post CMake: Build C++ Project for Windows, Linux and macOS appeared first on Code Pool.