1

I have multiple projects (subdirectories) inside my repository. All projects have only one executable file named main.cpp and they all use libraries from the common folder with #include statements. The folder structure looks like this:

root
|
├────common
|    ├──── example.h
|    ├──── example.cpp
|    ├──── *.h          # many header files
|    └──── *.cpp        # many source files
|
├────Project_A
|    ├──── CMakeLists.txt
|    └──── main.cpp
|
├────Project_B
|    ├──── CMakeLists.txt
|    └──── main.cpp
|
└──── CMakeLists.txt

This is my attempt at writing the root's CMakeLists.txt

cmake_minimum_required (VERSION 3.8)
project ("root")

file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
link_libraries(${CommonLibs})

add_subdirectory ("Project_A")
add_subdirectory ("Project_B")

Project_A's CMakeLists.txt

cmake_minimum_required (VERSION 3.8)
add_executable (Project_A "main.cpp")

Project_B's CMakeLists.txt

cmake_minimum_required (VERSION 3.8)
add_executable (Project_B "main.cpp")

However when running any of the projects I get this error:

LNK1107 invalid or corrupt file: cannot read at 0x7AC, file example.h

I don't believe the file is corrupted because before I tried to use link_libraries() in root's CMakeLists.txt I was getting other error:

Unresolved external symbol SomeNamespace::ExampleClass::ExampleClass(bool)

Possible duplicates

Other questions such as this one don't solve my problem because they usually work with a more complex folder structure. Also there are questions that attempt to target only single project like this one, but I have multiple projects.

Can you please provide a concise solution?

Kevin
  • 16,549
  • 8
  • 60
  • 74
sanitizedUser
  • 1,723
  • 3
  • 18
  • 33

2 Answers2

2

Add a CMakeLists.txt to your common/ directory:

root
|
├────common
|    ├──── CMakeLists.txt <-------- Add this
|    ├──── example.h
....

common/CMakeLists.txt

file(GLOB_RECURSE CommonLibsFiles ${CMAKE_CURRENT_SRC_DIR}/*.cpp)
add_library(CommonLibs ${CommonLibsFiles})
...

root's CMakeLists.txt

...

### NO NEED FOR THESE
file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
link_libraries(${CommonLibs})
###

add_subdirectory(common) #CommonLibs will now be visible to children directories
...

Now link the libraries as required. For example for project A:

Project_A's CMakeLists.txt

cmake_minimum_required (VERSION 3.8)
add_executable (Project_A "main.cpp")
target_link_libraries(Project_A PRIVATE CommonLibs) #link to common libs here,

All the targets/variables that are created or are visible to parent cmake file, are visible to children. The reverse is not true though. For children to expose their variables to parent, they need to explicitly specify PARENT_SCOPE

Waqar
  • 8,558
  • 4
  • 35
  • 43
  • I tried this but two errors emerged: `CMake Error at common/CMakeLists.txt:4 (add_library): Cannot find source file: CommonLibsFiles - Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx` And this one: `CMake Error at common/CMakeLists.txt:4 (add_library): No SOURCES given to target: CommonLibs` – sanitizedUser Jun 26 '20 at 18:14
  • 2
    Ah, you have to wrap it in braces, `${CommonLibsFiles}` – Waqar Jun 26 '20 at 18:33
2

The following lines in your top-level CMake do not make much sense:

file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
link_libraries(${CommonLibs})

The link_libraries() command accepts libraries or library targets, not variables (such as CommonLibs). You can use the CommonLibs variable to define a new library target, then link the library target to your executables using link_libraries():

file(GLOB_RECURSE CommonLibs ${CMAKE_SOURCE_DIR}/common/*.cpp)
# Add this line.
add_library(MyCommonLib SHARED ${CommonLibs})
link_libraries(MyCommonLib)

Please note that the use of link_libraries() in general is discouraged, even in CMake documentation itself. You should prefer linking your MyCommonLib to the specific executables that require it using target_link_libraries.

target_link_libraries(Project_A PRIVATE MyCommonLib)
Kevin
  • 16,549
  • 8
  • 60
  • 74