sbmlteam / libsbml

LibSBML is a native library for reading, writing and manipulating files and data streams containing the Systems Biology Markup Language (SBML). It offers language bindings for C, C++, C#, Java, JavaScript, MATLAB, Perl, PHP, Python, R and Ruby.
https://sbml.org/software/libsbml
Other
39 stars 28 forks source link

Building libsbml and its dependencies in the same project #227

Open luciansmith opened 2 years ago

luciansmith commented 2 years ago

I have a problem. I'm trying to build libsbml in a project where libsbml's dependencies are also being built at the same time. The problem is that when libsbml tries to find expat, it sees that expat hasn't been built yet, and fails. However, this is to be expected: the system is going to build both expat and libsbml; it just has to wait.

Here's the relevant bits of my CMakeLists.txt file:

#expat
set (EXPAT_SHARED_LIBS OFF)
set (EXPAT_BUILD_EXAMPLES OFF)
set (EXPAT_BUILD_TESTS OFF)
set (EXPAT_BUILD_TOOLS OFF)
set (EXPAT_BUILD_TOOLS OFF)
if (WITH_STATIC_RUNTIME)
    #expat is overriding this
  set(EXPAT_MSVC_STATIC_CRT ON CACHE BOOL "Use /MT flag (static CRT) when compiling in MSVC" FORCE)
endif()

add_subdirectory(expat/expat)

set(EXPAT_INCLUDE_DIR "$<TARGET_PROPERTY:expat,INCLUDE_DIRECTORIES>")
set(EXPAT_LIBRARY "$<TARGET_LINKER_FILE:expat>")

# libsbml
message(STATUS "Adding libsbml as subdirectory")
set(WITH_EXPAT ON CACHE BOOL "Compile libsbml with the expat library" FORCE)
set(WITH_LIBXML OFF CACHE BOOL "Compile libsbml with libxml (off by default)" FORCE)
add_subdirectory(libsbml)

and here's the error message I get from CMake:

CMake Error at third_party/libsbml/CMakeModules/FindEXPAT.cmake:163 (message):
  Unable to compile a test executable against expat with

    EXPAT_INCLUDE_DIR = $<TARGET_PROPERTY:expat,INCLUDE_DIRECTORIES>
    EXPAT_LIBRARY     = $<TARGET_LINKER_FILE:expat>

Call Stack (most recent call first):
  third_party/libsbml/CMakeLists.txt:422 (find_package)

If I comment out the lines defining EXPAT_INCLUDE_DIR and EXPAT_LIBRARY, I get:

CMake Error at C:/Program Files/CMake/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find EXPAT (missing: EXPAT_LIBRARY EXPAT_INCLUDE_DIR)
Call Stack (most recent call first):
  C:/Program Files/CMake/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  third_party/libsbml/CMakeModules/FindEXPAT.cmake:179 (find_package_handle_standard_args)
  third_party/libsbml/CMakeLists.txt:422 (find_package)
fbergmann commented 2 years ago

The expat find script compiles against expat, to see whether further compile definitions are necessary to compile against it. I suppose we could skip those tests in case you already define a expat target. In any case instead for you defining the expat library and include dir, it should be fine to define

add_library(EXPAT::EXPAT ALIAS expat)

and try the following patch:


diff --git a/CMakeLists.txt b/CMakeLists.txt
index 53a0d2eaf..a7b840729 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -419,7 +419,9 @@ set(LIBSBML_XML_LIBRARY_LIBS)

 if(WITH_EXPAT)

+    if(NOT TARGET EXPAT::EXPAT)
     find_package(EXPAT REQUIRED)
+    endif()

     add_definitions( -DUSE_EXPAT )
     list(APPEND SWIG_EXTRA_ARGS -DUSE_EXPAT)
luciansmith commented 2 years ago

That worked! Or at least, I could make it work. I had to 'FORCE' the expat library settings; apparently I need to FORCE anything in libsbml I want to set in CMake itself:

add_subdirectory(expat/expat)
add_library(EXPAT::EXPAT ALIAS expat)
set(EXPAT_INCLUDE_DIR "$<TARGET_PROPERTY:expat,INCLUDE_DIRECTORIES>" CACHE PATH "Expat incude directory" FORCE)
set(EXPAT_LIBRARY "$<TARGET_LINKER_FILE:expat>" CACHE FILEPATH "Expat library" FORCE)
set(WITH_EXPAT ON CACHE BOOL "Compile libsbml with the expat library" FORCE)
set(WITH_LIBXML OFF CACHE BOOL "Compile libsbml with libxml (off by default)" FORCE)

I assume you'll want to do the same with the other XML libraries, too? And the ZIP libraries?

fbergmann commented 2 years ago

I'm not entirely sure why you need the force for the WITH_EXPAT / WITH_LIBXML entries. As they should have just been taken from the definitions if you have a new enough cmake. But i dont mind to have the if (not target ... around the find_package statements.

luciansmith commented 2 years ago

If I leave them out entirely, they aren't defined, and libsbml won't compile, complaining that it doesn't know where 'zconf.h' is. If I put them in like I had originally, they get replaced by the generic UNKNOWN stand-ins. I had to define them with FORCE to get them to work.

fbergmann commented 2 years ago

zconf indicates, that potentiall the zlib target is missing some adjustments for your usecase.

tbh: i always prefered to have dependencies be built once, instead of all the time together with the actual target you want to build. So while i think it is good to support your usecase, i think it is not the way to focus on. Dependencies can be cached with a ccache action. And i hope that is what we are doing (still learning on that myself).

skeating commented 1 month ago

has this been resolved?

luciansmith commented 4 weeks ago

I had just made my own branch and used that forever, but I'm now trying to revert back to 'development'. It seems that everything now mostly works, except that the zlib.h check incorrectly fires. #388 added.