Saturday, October 30, 2021

[SOLVED] Cmake undefined reference when linking with a library that uses another library built with a Python script

Issue

I am new to cmake and I am trying to port a project of mine previously built with handwritten makefiles. The executable uses a lib "core" that I build that needs the lib "xed" (written by intel). Xed uses a python script to be built so in the CMakeLists to build my lib core, I used an "add_custom_command" to build xed following the instructions provided by intel:

project(libcore VERSION 0.1)
find_package(Python3 COMPONENTS Interpreter REQUIRED)

add_library(core STATIC src/arch.cpp src/cpu.cpp src/floppy.cpp src/pic.cpp src/pit.cpp src/ports.cpp src/ppi.cpp src/ram.cpp third-party/lib/libxed.a)

add_custom_command(OUTPUT third-party/lib/libxed.a
                    COMMAND ${CMAKE_COMMAND} -E make_directory third-party/xed/build
                    COMMAND ${PYTHON3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/third-party/xed/xed/mfile.py --jobs=4 --build-dir=third-party/xed/build/obj --src-dir=${CMAKE_CURRENT_SOURCE_DIR}/third-party/xed/xed --static --opt=3 --prefix=third-party --install-dir=third-party/xed/kits/xed-install-date-os-cpu --no-amd --no-via --no-encoder --compress-operands install
                    )

target_include_directories(core PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/third-party/include PUBLIC ${PROJECT_SOURCE_DIR}/include)

target_precompile_headers(core PUBLIC include/pch.hpp)

The problem is that when linking my final product with my lib "libcore.a" I have a lot of undefined references to the functions xed and I don't know how to fix that


Solution

There are two problems at once here: when trying to porting to cmake I tryed to mimic the way my makefiles worked. When I was thinking about how to embed libxed into my libcore I thought I was doing it in my makefiles but I wasn't, I was linking the final executable with my libcore and libxed. So the two problems are :

  1. how to embed a .a file into another
  2. how to do it with a makefile

The first question is answered here.

What I did is :

  1. create the first lib (in my case libxed.a)
  2. use the -x option of ar to extract the .o files of the first lib (in my case ar -x <path to libxed.a>/libxed.a
  3. create the new lib with all the .o files : ar -x *.o

I have to do all these steps because the process of compiling xed is a bit odd and it's hard to know in advance which source file to include

I still don't know how to mimic this behaviour in CMake in a portable way but if necessary it will be for another post on StackOverflow, so I will mark this as an accepted answer



Answered By - Adrien