Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fmt 7.0.0 + shared + Visual Studio : Undefined References #1756

Closed
SpaceIm opened this issue Jul 7, 2020 · 3 comments
Closed

fmt 7.0.0 + shared + Visual Studio : Undefined References #1756

SpaceIm opened this issue Jul 7, 2020 · 3 comments

Comments

@SpaceIm
Copy link

SpaceIm commented Jul 7, 2020

(maybe same issue than #1753, but different compiler)

Since 7.0.0, these two simple test programs fail to link when fmt is built as a shared lib with Visual Studio (2017 and 2019, maybe others versions). It works if fmt is header only or static.

CMakeLists.txt:

cmake_minimum_required(VERSION 3.1.2)
project(test_package CXX)

find_package(fmt REQUIRED CONFIG)

# TEST_PACKAGE #################################################################
add_executable(${CMAKE_PROJECT_NAME} test_package.cpp)
set_property(TARGET ${CMAKE_PROJECT_NAME} PROPERTY CXX_STANDARD 14)
if(FMT_HEADER_ONLY)
    target_link_libraries(${CMAKE_PROJECT_NAME} fmt::fmt-header-only)
else()
    target_link_libraries(${CMAKE_PROJECT_NAME} fmt::fmt)
endif()

# TEST_RANGES ##################################################################
add_executable(test_ranges test_ranges.cpp)
set_property(TARGET test_ranges PROPERTY CXX_STANDARD 14)
if(FMT_HEADER_ONLY)
    target_link_libraries(test_ranges fmt::fmt-header-only)
else()
    target_link_libraries(test_ranges fmt::fmt)
endif()

test_package.cpp:

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <limits>


#include "fmt/format.h"
#include "fmt/printf.h"
#include "fmt/ostream.h"
#include "fmt/color.h"


void vreport(const char *format, fmt::format_args args) {
    fmt::vprint(format, args);
}

template <typename... Args>
void report(const char *format, const Args & ... args) {
    vreport(format, fmt::make_format_args(args...));
}

class Date {
    int year_, month_, day_;
  public:
    Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}

    friend std::ostream &operator<<(std::ostream &os, const Date &d) {
        return os << d.year_ << '-' << d.month_ << '-' << d.day_;
    }
};

int main() {
    const std::string thing("World");
    fmt::print("PRINT: Hello {}!\n", thing);
    fmt::printf("PRINTF: Hello, %s!\n", thing);

    const std::string formatted = fmt::format("{0}{1}{0}", "abra", "cad");
    fmt::print("{}\n", formatted);

    fmt::memory_buffer buf;
    fmt::format_to(buf, "{}", 2.7182818);
    fmt::print("Euler number: {}\n", fmt::to_string(buf));

    const std::string date = fmt::format("The date is {}\n", Date(2012, 12, 9));
    fmt::print(date);

    report("{} {} {}\n", "Conan", 42, 3.14159);

    fmt::print(std::cout, "{} {}\n", "Magic number", 42);

    fmt::print(fg(fmt::color::aqua), "Bincrafters\n");

    return EXIT_SUCCESS;
}

test_ranges.cpp:

#include <cstdlib>
#include <vector>
#include "fmt/ranges.h"

int main() {
    std::vector<char> numbers;
    fmt::format_to(std::back_inserter(numbers), "{}{}{}", 1, 2, 3);
    const std::string str_numbers = fmt::format("{}", numbers);
    fmt::print("numbers: {}\n", str_numbers);
    return EXIT_SUCCESS;
}

Errors:

test_package.obj : error LNK2019: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl fmt::v6::detail::vformat(class fmt::v6::basic_string_view<char>,struct fmt::v6::format_args)" (?vformat@detail@v6@fmt@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$basic_string_view@D@23@Uformat_args@23@@Z) referenced in function main
test_ranges.obj : error LNK2019: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl fmt::v6::detail::vformat(class fmt::v6::basic_string_view<char>,struct fmt::v6::format_args)" (?vformat@detail@v6@fmt@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$basic_string_view@D@23@Uformat_args@23@@Z) referenced in function main

Might be related to modifications made into core.h for FMT_EXTERN_TEMPLATE_API ? AFAIK, for Visual Studio (but not others compiler on Windows) FMT_EXTERN_TEMPLATE_API shouldn't be __declspec(dllexport) at build time, only FMT_INSTANTIATION_DEF_API.
Seems like also that changes made to FMT_EXTERN_TEMPLATE_API now prevent to build fmt with fvisibility hidden for GNU compilers.

EDIT:
explicit instantiation definition of std::string internal::vformat<char>(string_view, basic_format_args<format_context>) has been removed from format.cc in 7.0.0. Therefore it has no chance to be exported I guess.

@prince-chrismc
Copy link

Might be fixed #1757

@vitaut
Copy link
Contributor

vitaut commented Jul 7, 2020

Does #1757 fix the error?

@SpaceIm
Copy link
Author

SpaceIm commented Jul 7, 2020

Yes it works, thanks @Kurkin

@vitaut vitaut closed this as completed Jul 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants