Skip to content

Linking against wrong library path #17

Open
@hugolm84

Description

@hugolm84

Hi!

Using

Node 16.13.1 and CMake 3.24.3 I fail to link against boost libraries via

include(BoostLib)

require_boost_libs("1.69.0" "date_time")
target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})

I get error:

make[2]: *** No rule to make target '~/.cmake-js/boost/1.69.0/stage/lib/libboost_iostreams-mt-d.a', needed by 'Debug/CppAddon.node'.  Stop.

for both OSX and Linux.

The issue is that BoostLibInstaller.cmake is setting the lib_path:

if((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "") OR (NOT DEFINED CMAKE_BUILD_TYPE))
    set(lib_path "${install_dir}/${stage_dir}/lib/libboost_${lib_name}-mt-d.a")
else()
    set(lib_path "${install_dir}/${stage_dir}/lib/libboost_${lib_name}-mt.a")
endif()

that is used:

set_target_properties(${boost_lib} PROPERTIES
    IMPORTED_LOCATION "${lib_path}"
    LINKER_LANGUAGE CXX)

However, using the b2 args:

Linux:

link=static;threading=multi;runtime-link=shared;--build-dir=Build;stage;--stagedir=stage;-d+2;--hash;--ignore-site-config;variant=debug;--layout=tagged;-sNO_BZIP2=1;cxxflags=-fPIC;cxxflags=-std=c++11;toolset=gcc

OSX:

link=static;threading=multi;runtime-link=shared;--build-dir=Build;stage;--stagedir=stage;-d+2;--hash;--ignore-site-config;variant=debug;toolset=clang;cxxflags=-fPIC;cxxflags=-std=c++11;cxxflags=-stdlib=libc++;linkflags=-stdlib=libc++;architecture=combined;address-model=32_64;--layout=tagged

will generate binaries like:

Linux:

libboost_chrono-mt-d-x64.a

OSX:

libboost_chrono-mt-d-c32_64.a

Linking will later fail, as the path is set to the non existing libboost_chrono-mt-d.a lib.

I am not sure why these suffixes are added by BOOST build system, but the BoostLibInstaller.cmake can be patched like so:

if(UNIX)
    set(LIBSUFFIX "-x32")
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
            set(LIBSUFFIX "-x64")
    endif()
endif()
if(APPLE)
    string(REGEX MATCH "address-model\\=([0-9_]+)" model "${b2Args}")
    set(ADDRESS_MODEL ${CMAKE_MATCH_1})
    set(LIBSUFFIX "-c${ADDRESS_MODEL}")
endif()
if((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "") OR (NOT DEFINED CMAKE_BUILD_TYPE))
    set(lib_path "${install_dir}/${stage_dir}/lib/libboost_${lib_name}-mt-d${LIBSUFFIX}.a")
else()
    set(lib_path "${install_dir}/${stage_dir}/lib/libboost_${lib_name}-mt${LIBSUFFIX}.a")
endif()

which is a bit better than the symlink step users of the BoostLib can use instead:

if (Boost_FOUND)
    # https://github.com/cmake-js/boost-lib/blob/master/cmake/GetBoostLibB2Args.cmake
    get_boots_lib_b2_args()
    string(REGEX MATCH "address-model\\=([0-9_]+)" model "${b2Args}")
    set(ADDRESS_MODEL ${CMAKE_MATCH_1})
    if(APPLE)
        set(ADDRESS_MODEL "c${ADDRESS_MODEL}")
    endif()
    if (NOT ADDRESS_MODEL OR ADDRESS_MODEL STREQUAL "")
        set(ADDRESS_MODEL "x64") # Lets assume x64 for linux
    endif()
    string(REGEX MATCH "variant\\=([A-Za-z0-9_])" variant "${b2Args}")
    set(VARIANT "-${CMAKE_MATCH_1}")

    foreach(lib ${Boost_LIBRARIES})
        set(want_lib "lib${lib}-mt${VARIANT}.a")
        set(have_lib "lib${lib}-mt${VARIANT}-${ADDRESS_MODEL}.a")
        if(NOT EXISTS "${Boost_INCLUDE_DIR}/stage/lib/${want_lib}")
            EXECUTE_PROCESS(COMMAND ln -sf ${have_lib} ${want_lib}
                WORKING_DIRECTORY "${Boost_INCLUDE_DIR}/stage/lib"
            )
            message(STATUS "Symlinked ${Boost_INCLUDE_DIR}/stage/lib/${have_lib} -> ${Boost_INCLUDE_DIR}/stage/lib/${want_lib}")
        endif()
    endforeach()
endif()

Best would be if the b2 output lib did not get prefixed...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions