Portable programming - Linking fails fails with Win32 but links with linux
Question: I am working on a portable application which is running under Linux and
Windows. I am cross compiling on a linux system using cmake, gcc 4.4.4 and
mingw-gcc 4.4.4.

I can compile and link the Linux version of my application without problems.
However if I try to cross-compile for Windows, the application compiles fine,
but the linker ends with an 'undefined reference' error.

Here is the excerpt from the source code:

Header File (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);
    };
    

Source file (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 */
    }
    

Excerpt from code which causes the link-error:

    
    
    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 */
    } 
    

As said, above code links fine if I compile for linux system, but fails if I
use mingw to compile for Win32. The exact linker error is:

    
    
    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 &
    )'
    

The file fileactions.cpp is linked into a static libray libtmm. The TmmProject
class, which causes the error, is part of the the same library.

The CMakeLists.txt which is used to link the library looks like this
(shortened):

    
    
    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 )
    

Has anyone an Idea what could be the reason for the failure?


Answer: Microsoft is using a lot of defines in their header for unicode support. In
your case the name `OpenFile` seems also to be defined to be eiter `OpenFileA`
or if you switch to unicode it would be `OpenFileW`.  
To get rid of this problem add this after including the headers from
microsoft.

    
    
    #undef CopyFile
    

You can of course pack it into a `#ifdef` to limit it to the microsoft
platform.

