heych
heych

Reputation: 33

Converting Makefile to CMake cannot find linked shared object

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.

Upvotes: 1

Views: 466

Answers (2)

David Hoy
David Hoy

Reputation: 21

There's an easier way to do all this. I happen to be using the same toolchain, and likely the exact same iWave telematic device that you are. My CMakeLists.txt file is generic, nothing toolchain-specific in it at all (except the platform-specific library)...

cmake_minimum_required(VERSION 3.0.0)
project(testapp VERSION 0.1.0)

add_executable(testapp src/testapp.cpp)

target_include_directories(testapp PUBLIC include)

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_directories(testapp PUBLIC lib)
target_link_libraries(testapp PRIVATE Threads::Threads libOBD2.so)

Once I have this file in my project folder, I run the following commands from the terminal:

source /opt/fsl-imx-x11/5.4-zeus/environment-setup-cortexa7t2hf-neon-poky-linux-gnueabi
mkdir build
cd build
cmake ..
make

CMake will now automatically detect the toolchain, and generate the appropriate makefiles to actually build your project. The nice thing is, if you're not linking in platform-specific libraries (such as the libOBD2.so file provided by iWave), you can easily retarget the build to another environment - I've successfully switched to a Raspberry Pi, or native Ubuntu. It all depends on what toolchain CMake detects when you run it. The "source" command sets that up, and CMake takes it all from there...

Regards, David

Upvotes: 0

heych
heych

Reputation: 33

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").

Upvotes: 1

Related Questions