Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.2k views
in Technique[技术] by (71.8m points)

linker - I am missing something fundamental with CMake in a complex library dependency structure

I have a complex build project that started as 4 visual studio 2017 solution C++/Fortran projects. I need to port them to Linux. We were planning the port from the beginning (5 years ago) using cross-platform compatible coding practices but it wasn't until recently that we were directed to actually start the port. I used a python cmake-converter to get me started. This worked remarkably well, until I got to linking. Below is the structure of the system, abstracted for brevity

cmake_base
 - fortran_libs
  - f1static
  - f2static
  ...
  - f7static
- cpp_libs
  - c1static
  - c2static
  ...
  - cpp_API_shared
  - Java_API_shared
- utilities
- tests

each of these directories has a CMakeList.txt, and I use the idiom

cd cmake_base 
mkdir build
cd build
cmake ..
make

to start the build.

I have been successful to the point that the several dozen static libraries build. each .a ends up in a parallel directory structure such as cmake_base/build/fortran_libs/f1static/libf1static.a

What now has me stymied is that I need to build the two shared libraries which are APIs wrapping the functionality of all the static libraries from the fortran_libs and cpp_libs projects (as well as some libraries I've installed such as openssl and GEOS). The shared libraries are being linked, but they only contain the wrapping and data marshalling, none of the functionality. I am trying to write my CMake code as recommended in Effective Modern CMake.

I started trying to use find_package(c1static REQUIRED) paired with target_link_libraries(cppAPI_shared c1static) in the CMakeLists.txt file in the cpp_API_shared directory, but find is looking for c1staticConfig.cmake which does not exist, so I'm obviously missing additional infrastructure in one or more CMakeLists.txt files in the hierarchy.

I think I could make things work using the link_directories and link_libraries commands, but I would prefer to solve the issue using the more modern way of thinking. I don't want to "install" all the static libraries, but I do want to install the two API libraries. The utilities and tests project will simply use the installed .so libraries to link against, so once I have the two API libraries built and installed in their correct location (/usr/local/lib/...) the executables should be a relatively easy as they only need to link to cpp_api.so

Any guidance would be appreciated.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Thank you for your responses. after a lot of searching, I found the answer.

The root issue is that unlike Visual Studio under Windows, Linux does not like linking static libraries into a shared library.

The concept I was missing in CMake was that of the OBJECT library.

add_library(native OBJECT ${sources})

This compiles the source to object, but does not link them. Up one or more directories the CMakeLists.txt references this using code that looks like this:

 add_library(ENWEDS_Native SHARED
          $<TARGET_OBJECTS:native>
          $<TARGET_OBJECTS:enweds_fortran>
          $<TARGET_OBJECTS:enweds_cpp>) 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...