0

File structure under folder /home/cyan/proj

fst | -- include | |-- fstlib | |-- fst_row_reader.h | |-- fst | |-- interface | |-- fststore.h | | -- lib |-- libfst.so test.cc CMakeLists.txt 

fst folder is a library I added and used in test.cc.

test.cc

#include <iostream> #include <fstlib/fst_row_reader.h> class Add{ public: double add2num(int a, double b){ return a + b; } }; extern "C" { Add* test_new(){ return new Add; } int my_func(Add* t, int a, double b){ return t->add2num(a, b); } } 

*Note: In my actual test.cc I used some functions in fst library. Here is just a sample for simplicity.

Problem

Previously, I can simply use g++ test.cc -fPIC -shared -o test.so to get the .so file. However, since I included the fst lib, I got the following error:

In file included from /home/cyan/proj/fst/include/fstlib/fst_row_reader.h:7:0, from read_fst.cc:1: /home/cyan/proj/fst/include/fstlib/fst_reader.h:6:10: fatal error: fstlib/fst/interface/fststore.h: No such file or directory #include <fstlib/fst/interface/fststore.h> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. 

My attempt:

$ g++ -L/home/cyan/proj/fst/lib -l:libfst.so /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status --------------------------------------------------------- $ g++ read_fst.cc -L /home/cyan/proj/fst/lib/libfst.so -fPIC -shared -o test.so In file included from /home/cyan/proj/fst/include/fstlib/fst_row_reader.h:7:0, from read_fst.cc:1: /home/cyan/proj/fst/include/fstlib/fst_reader.h:6:10: fatal error: fstlib/fst/interface/fststore.h: No such file or directory #include <fstlib/fst/interface/fststore.h> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. 

I also tried CMakeLists.txt to link the fst library as well as create a .so file under the path /home/cyan/proj/build/lib. But I am very new to CMake. Here is my attempt:

cmake_minimum_required(VERSION 3.0.0) project(MY_PROJ VERSION 0.1.0) set(mylibSRCS test.cc) message(STATUS "Build test.so") include_directories(${CMAKE_SOURCE_DIR}/fst/include) link_directories(${CMAKE_SOURCE_DIR}/fst/lib) add_library(MY_PROJ SHARED ${mylibSRCS}) set_target_properties(MY_PROJ PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) target_link_libraries(MY_PROJ ${CMAKE_SOURCE_DIR}/fst/lib/libfst.so) # link to my fst lib target_link_libraries(MY_PROJ) 

But I can't find any files under the /home/cyan/proj/build/lib. I guess this is my CMake command issue. Could you please help me with this problem?

3
  • You create a variable LIBRARY_OUTPUT_PATH which has no special meaning for CMake. Correct name of variable which controls output directory of the shared library is CMAKE_LIBRARY_OUTPUT_DIRECTORY. See that answer: stackoverflow.com/a/3744130/3440745. Commented Mar 23, 2022 at 18:53
  • @Tsyvarev thx for answering. I tried. Unfortunately I still couldn't find any files under the path Commented Mar 23, 2022 at 18:57
  • Setting property LIBRARY_OUTPUT_DIRECTORY works for me. You could print value of variable PROJECT_BINARY_DIR to be sure it points to the expected directory (/home/cyan/proj/build): message(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}"). Commented Mar 23, 2022 at 19:25

1 Answer 1

1

The most convenient way of using a library located on the file system imho associating the info with a imported library target which allows you to just link it using target_link_libraries:

add_library(fst SHARED IMPORTED) target_include_directories(fst INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/fst/include) set_target_properties(fst PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/fst/lib/libfst.so) ... target_link_libraries(MY_PROJ PRIVATE fst) 

this way the info is easy to reuse and it listed in a single place instead of spreading it into different target properties of the linking target.

A bit more advanced, but even better would be to write fst-config.cmake and fst-config-version.cmake files and putting them in the "installation directory" of the library which would allow you to use find_package(fst) to execute the logic creating the imported library which makes the library simple to reuse across multiple cmake projects, but this is beyond the scope of this answer. The find_package documentation provides more info about how to do this.


Btw: Note the use of CMAKE_CURRENT_SOURCE_DIR instead of CMAKE_SOURCE_DIR. If you're specifying absolute paths inside the directory containing the CMakeLists.txt file containing the variable reference, since CMAKE_SOURCE_DIR refers to the toplevel source dir which may be different, if you're including the CMakeLists.txt using add_subdirectory.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I tried to generate a static lib instead of a shared lib then it works. The reason for failing to get shared lib is irrelevant to this question, so this problem can be regarded as solved. The last thing is I can only use include_directories instead of target_include_directories, which is supposed to be a scaling issue. Thanks again!
@Cyan any references to why target_include_directories is supposed to be a scaling issue? As long as your library targets link your other library targets "as private as possible", there shouldn't be too many include dirs for the compiler to consider and adding the info at directory scope could result in the include directories accidentally being added to targets should another target be created in the CMakeLists.txt or one added via add_subdirectory...
for my case target_include_directories generates a config error: Cannot specify include directories for imported target "fst", but include_directories works, which I don't quite understand
Oh, right... That requires cmake >= 3.11... Probably setting the INTERFACE_INCLUDE_DIRECTORIES target property does the trick for older cmake versions...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.