Friday, April 22, 2022

[SOLVED] Converting Makefile to CMake cannot find linked shared object

Issue

I am attempting to convert a working Makefile into a CMake and need a little assistance. I am trying to cross compile a small program for a yocto device from a Ubuntu20 machine that is trying to link to the devices shared object file with cmake. I have a working Makefile that builds a working program. However, when I try and do this with a CMakeList file it fails at the make stage linking to the shared objects linker flag.

The file structure of the code is as follows;

Parent
  - include/
      - file1.h
      - file2.h
      - xxx.h
  - lib/
      - libOBD2.so 
  - src/
      - test.c
  - CMakeLists.txt   # Not working
  - Makefile.        # working

The shared object is being linked from within the program parent directory but I have also tried with it in the /usr/lib and /usr/local/lib from here but with no change.

The working Makefile

.prevent_execution:
exit 0

#remove @ for no make command prints
DEBUG = @

APP_DIR = .
BUILD_DIR := $(APP_DIR)/build
SRC_DIRS := $(APP_DIR)/src
HEADER_DIR := $(APP_DIR)/include
APP_LIBRARY_DIR = $(APP_DIR)/lib
APP_NAME = test

# Locate all the source c and cpp files to be built
APP_SRC_FILES := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c')

INC_DIRS := $(shell find $(HEADER_DIR) -type d)
# Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))

CFLAGS+=-fPIC

PATH1 = /opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/include/
PATH2 = /opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/include/libxml2/
PATH3 = /opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi/usr/lib/

MAKE_CMD = -g -O0 -s -o $(BUILD_DIR)/$(APP_NAME) $(INC_FLAGS) $(APP_SRC_FILES) -    I$(PATH1) -I$(PATH2) -L$(APP_LIBRARY_DIR) -lz -lOBD2 -lssl -lcrypto -lcurl -lxml2 -L$(PATH3) -lm -ldl -lpthread -lrt

all:
    $(DEBUG) $(CC) $(CFLAGS) $(MAKE_CMD)

clean:
    rm -f $(BUILD_DIR)/$(APP_NAME)

The CmakeLists.txt

cmake_minimum_required( VERSION 3.5 )
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR ARM)

# -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

project(iwtest)

set(PATH1 "/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/include/")
set(PATH2 "/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/include/libxml2/")
set(PATH3 "/opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi/usr/lib")

set(LIB_DIR "${CMAKE_SOURCE_DIR}/lib")

include_directories(${PROJECT_NAME} PRIVATE ${PATH1})
include_directories(${PROJECT_NAME} PRIVATE ${PATH2})
include_directories(${PROJECT_NAME} PRIVATE "${PROJECT_SOURCE_DIR}/include")

set(SOURCE_FILES src/test.c)

add_definitions("-g")
add_definitions("-O0")
add_definitions("-s")

# Connect the libOBD2 library to the project
add_library(libOBD2 SHARED IMPORTED)
set_target_properties(libOBD2 PROPERTIES IMPORTED_LOCATION ${LIB_DIR}/libOBD2.so)
include_directories(libOBD2 INTERFACE ${CMAKE_SOURCE_DIR}/lib)

add_executable(${PROJECT_NAME} ${SOURCE_FILES})

# target_link_libraries(${PROJECT_NAME} PRIVATE ${PATH3})
target_link_libraries(${PROJECT_NAME} PUBLIC libOBD2)

target_link_options(${PROJECT_NAME} PRIVATE -lz -lOBD2 -lssl -lcrypto -lcurl -lxml2 -L$(PATH3) -lm -ldl -lpthread -lrt)
# target_link_options(${PROJECT_NAME} PRIVATE -I$(PATH1) -I$(PATH2) -L$(LIB_DIR) -lz -lOBD2 -lssl -lcrypto -lcurl -lxml2 -L$(PATH3) -lm -ldl -lpthread -lrt)

The output of cmake

-- Toolchain file defaulted to '/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/share/cmake/OEToolchainConfig.cmake'
-- The C compiler identification is GNU 9.2.0
-- The CXX compiler identification is GNU 9.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dev/Workspace/build/cmakebuild

The output of make VERBOSE=1

/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/cmake -S/home/dev/Development/iwave-test-code -B/home/dev/Workspace/build/cmakebuild --check-build-system CMakeFiles/Makefile.cmake 0
/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/cmake -E cmake_progress_start /home/dev/Workspace/build/cmakebuild/CMakeFiles /home/dev/Workspace/build/cmakebuild//CMakeFiles/progress.marks
make  -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/dev/Workspace/build/cmakebuild'
make  -f CMakeFiles/iwtest.dir/build.make CMakeFiles/iwtest.dir/depend
make[2]: Entering directory '/home/dev/Workspace/build/cmakebuild'
cd /home/dev/Workspace/build/cmakebuild && /opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/dev/Development/iwave-test-code /home/dev/Development/iwave-test-code /home/dev/Workspace/build/cmakebuild /home/dev/Workspace/build/cmakebuild /home/dev/Workspace/build/cmakebuild/CMakeFiles/iwtest.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/dev/Workspace/build/cmakebuild'
make  -f CMakeFiles/iwtest.dir/build.make CMakeFiles/iwtest.dir/build
make[2]: Entering directory '/home/dev/Workspace/build/cmakebuild'
[ 50%] Building C object CMakeFiles/iwtest.dir/src/test.c.o
/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc   -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7 -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi --sysroot=/opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi  -I/home/dev/Development/iwave-test-code/iwtest -I/home/dev/Development/iwave-test-code/PRIVATE -I/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/include -I/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/include/libxml2 -I/home/dev/Development/iwave-test-code/include -I/home/dev/Development/iwave-test-code/libOBD2 -I/home/dev/Development/iwave-test-code/INTERFACE -I/home/dev/Development/iwave-test-code/lib -O2 -pipe -g -feliminate-unused-debug-types  -fPIE   -g -O0 -s -o CMakeFiles/iwtest.dir/src/test.c.o -c /home/dev/Development/iwave-test-code/src/test.c
In file included from /opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi/usr/include/bits/libc-header-start.h:33,
                 from /opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi/usr/include/stdio.h:27,
                 from /home/dev/Development/iwave-test-code/src/test.c:1:
/opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi/usr/include/features.h:382:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp]
  382 | #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
      |    ^~~~~~~
[100%] Linking C executable iwtest
/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/cmake -E cmake_link_script CMakeFiles/iwtest.dir/link.txt --verbose=1
/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc   -mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7 -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi --sysroot=/opt/fsl-imx-x11/5.4-zeus/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi  -O2 -pipe -g -feliminate-unused-debug-types  -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -fstack-protector-strong -Wl,-z,relro,-z,now -lz -lOBD2 -lssl -lcrypto -lcurl -lxml2 "-L\$$(PATH3)" -lm -ldl -lpthread -lrt CMakeFiles/iwtest.dir/src/test.c.o -o iwtest  -Wl,-rpath,/home/dev/Development/iwave-test-code/lib /home/dev/Development/iwave-test-code/lib/libOBD2.so 
/opt/fsl-imx-x11/5.4-zeus/sysroots/x86_64-pokysdk-linux/usr/libexec/arm-poky-linux-gnueabi/gcc/arm-poky-linux-gnueabi/9.2.0/real-ld: cannot find -lOBD2
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/iwtest.dir/build.make:104: iwtest] Error 1
make[2]: Leaving directory '/home/dev/Workspace/build/cmakebuild'
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/iwtest.dir/all] Error 2
make[1]: Leaving directory '/home/dev/Workspace/build/cmakebuild'
make: *** [Makefile:103: all] Error 2

Any help is much appreciated. Thanks in advance.


Solution

Thanks to Tsyvarev comment the solution was to remove the -lOBD2 from the target_link_options. As per Tsyvarev suggestion now all the linker options are linked through target_link_libraries.

The solution to the CMakeLists.txt

# remove the target_link_options line
# target_link_options(${PROJECT_NAME} PRIVATE -lz -lOBD2 -lssl -lcrypto -lcurl -lxml2 -L$(PATH3) -lm -ldl -lpthread -lrt) 

# replace with
target_link_libraries(${PROJECT_NAME} PUBLIC libOBD2 pthread ssl crypto curl xml2 m dl rt)

On a side note, as i was cross-compiling for a yocto device the libOBD2.so was located in a different directory to the cross-compile pc of ${CMAKE_SOURCE_DIR}/lib. To fix this I copied libOBD2.so to the same directory seen on the device, in this case it was /usr/lib and change LIB_DIR to set(LIB_DIR "/usr/lib").



Answered By - heych
Answer Checked By - Robin (WPSolving Admin)