modelon-community / fmi-library

C library for importing FMUs
Other
115 stars 34 forks source link

Merging static libs with MSVC does not work. #36

Open mahge opened 1 year ago

mahge commented 1 year ago

FMIL tries to merge static libs with the function merge_static_libs. However this does not seem to work with MSVC.

I am trying to debug the issue but looking at the code responsible for merging libs with MSVC https://github.com/modelon-community/fmi-library/blob/fc8d2ebdaefdaee65c9d22e450857f3c50d5fb44/Config.cmake/mergestaticlibs.cmake#L57-L69

I can not see anything relevant to actually merging the libraries.

Is there something else that does the merging? If so where is it located so we can continue debugging.

filip-stenstrom commented 1 year ago

As the comment on line 59 says, lib.exe accepts a list of static libs to produce a merged static lib. Line 66 sets the list of sub-libraries as a flag for producing outlib, which is the merged static library.

Documentation on lib.exe: https://learn.microsoft.com/en-us/cpp/build/reference/managing-a-library?view=msvc-170

mahge commented 1 year ago

As the comment on line 59 says, lib.exe accepts a list of static libs to produce a merged static lib. Line 66 sets the list of sub-libraries as a flag for producing outlib, which is the merged static library.

I understood that far but I can not see where the merging is actually done, i.e., where lib.exe is actually invoked.

mahge commented 1 year ago

I have fixed it on our fork using the following

# Now the easy part for MSVC and for MAC
  if(MSVC)
    # lib.exe does the merging of libraries just need to conver the list into string
    foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
        set(flags "")
        foreach(lib ${libfiles_${CONFIG_TYPE}})
            set(flags "${flags} ${lib}")
        endforeach()
        string(TOUPPER "STATIC_LIBRARY_FLAGS_${CONFIG_TYPE}" PROPNAME)
        set_target_properties(${outlib} PROPERTIES ${PROPNAME} "${flags}")
    endforeach()

+   find_program(MSVC_LIB_TOOL lib.exe)

+   if(NOT MSVC_LIB_TOOL)
+       message(FATAL_ERROR "LIB.EXE not found. fmil can not merge static libs.")
+   endif()

+   get_target_property(outfile ${outlib} LOCATION)
+   add_custom_command(TARGET ${outlib} POST_BUILD
+       COMMAND ${CMAKE_COMMAND} -E remove ${outfile}
+       COMMAND ${MSVC_LIB_TOOL} /OUT:${outfile} ${libfiles}
+   )

  elseif(APPLE)

You should update it accordingly.

filip-stenstrom commented 1 year ago

At the beginning of the function: add_library(${outlib} STATIC ${dummyfile})

Cmake should convert this to a call to lib.exe when compiling with MSVC. The libs to be merged are later added as flags.

It's tested with generator = Visual Studio 15 2017 Win64.

mahge commented 1 year ago

At the beginning of the function: add_library(${outlib} STATIC ${dummyfile})

Cmake should convert this to a call to lib.exe when compiling with MSVC. The libs to be merged are later added as flags.

I have to ask, why is that approach chosen? To me it sounds unconventional (even on top of merging static libs), confusing and brittle. I am still not sure how it is supposed to work that way.

It's tested with generator = Visual Studio 15 2017 Win64.

I am testing with Visual Studio 2019 Win64. Is the use of the merged library tested? The library will be built anyway but it does not contain any of the libraries that were supposed to be merged. Does

DUMPBIN /SYMBOLS fmilib.lib

show the symbols from the sublibs? For me it does not.