可移植编程——在Win32上链接失败,但在linux上链接失败

Portable programming - Linking fails fails with Win32 but links with linux

本文关键字:失败 链接 但在 linux 编程 可移植 Win32      更新时间:2023-10-16

我正在开发一个在Linux和Windows下运行的便携式应用程序。我使用cmake, gcc 4.4.4和mingw-gcc 4.4.4在linux系统上交叉编译。

我可以编译和链接我的应用程序的Linux版本没有问题。然而,如果我尝试在Windows上交叉编译,应用程序编译得很好,但链接器以"未定义的引用"错误结束。

以下是源代码的摘录:

头文件(fileactions.hpp):

class FileActions {
    bool CopyFile(const std::string &source, const std::string &destination);
    bool CopyFile(const boost::filesystem::path& source, const boost::filesystem::path& destination);
};

源文件(fileactions.cpp):

bool FileActions::CopyFile(const boost::filesystem::path& source, const boost::filesystem::path& destination)
{
    return this->CopyFile(source.string(), destination.string());
}
bool FileActions::CopyFile(const std::string &source, const std::string &destination)
{
    /* ... do something */
}

从导致链接错误的代码中摘录:

bool TmmProject::PostImportOldVersion(int old_version) {
    namespace fs = boost::filesystem;
    FileActions dd;
    fs::path backup;
    /* fs::path _location; // This is actually defined in the class declaration */
    /* do something more */
    if( !dd.CopyFile(_location, backup ) ) {  <-- I get the linker error at this line
        log << "<span style="color:red">Failed to create backup file. Stopping import </span><br>";
        log << "The error message is: " << dd.GetError() << "<br>";
        _last_error = log.str();
        return false;
    }
    /* do something more */
} 

如前所述,如果我在linux系统下编译,上面的代码链接良好,但如果我使用mingw来编译Win32,则会失败。确切的链接器错误是:

CMakeFiles/tmm.dir/tmmproject.cpp.obj:/.../tmm/tmmproject.cpp:408: undefined reference
to 'tmm::fileActions::CopyFileA(
   boost::filesystem::basic_path<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::filesystem::path_traits> const &, 
   boost::filesystem::basic_path<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::filesystem::path_traits> const &
)'

文件fileactions.cpp被链接到一个静态库libtmm。导致错误的TmmProject类是同一个库的一部分。

用于链接库的CMakeLists.txt看起来像这样(缩短):

include_directories( ... )
link_directories ( ${Boost_LIBRARY_DIRS} )
file(GLOB TMM_HEADERS *.h)
file(GLOB TMM_SOURCES *.cpp)
set ( TMM_LIBS 
  ${Boost_LIBRARIES}
  ${PYTHON_LIBRARIES}
  m
)
IF( WIN32 )
    ADD_LIBRARY( tmm STATIC ${TMM_SOURCES} )
    target_link_libraries( tmm ${TMM_LIBS} )
    # I found the following option from a similar quesiton in this froum, but
    # actually it does not seem to make any difference
    SET_TARGET_PROPERTIES( tmm PROPERTIES LINK_FLAGS -Wl,--export-all-symbols )
ELSE( WIN32 )
    ADD_LIBRARY( tmm SHARED ${TMM_SOURCES} )
    target_link_libraries( tmm ${TMM_LIBS} )
    INSTALL(TARGETS tmm DESTINATION lib)
ENDIF( WIN32 )

有人知道失败的原因是什么吗?

Microsoft在其header中使用了许多定义来支持unicode。在您的情况下,名称OpenFile似乎也被定义为OpenFileA,或者如果您切换到unicode,它将是OpenFileW
要解决这个问题,请在包含microsoft.

的头文件后添加这个。
#undef CopyFile

您当然可以将其打包到#ifdef中,以将其限制为microsoft平台。

这是微软使用宏允许应用程序使用"UNICODE"(宽或16位字符)和"ASCII"(8位字符)形式的系统调用。在windows。h中有这样的内容:

#if UNICODE
#define CopyFile CopyFileW
#else
#define CopyFile CopyFileA
#endif

虽然使用#undef CopyFile(和类似的)将工作,我建议你避免包括<windows.h>,除非绝对必要-如果你必须,尽量限制到一个小数量(理想情况下一个)源文件,实际上直接与Widnows交互。

相关文章: