11

I'm using cmake to build my project in C++. Assume I have the following directories on my Source folder

Source
  |_Dir1
  |   |_Class.cpp
  |   |_Class.hpp
  |
  |_Dir2
      |_Main.cpp

In Dir1 there's a class with its header and implementation files (Class.cpp and Class.hpp).

In Dir2 there's the main application which uses the class in Dir1

What is the good way to tell the CMakeLists in Dir2 to build the executable with Dir1/Class.cpp file?

EDIT: To be more specific, I want to define that the source file for Class.cpp has to be used in Dir1's CMakeLists.txt, and not in Dir2's. Doing it the other way feels plain wrong to me and it's hard to use, so if there's a reason they're enforcing me to do this some clarification on the topic would be nice.

What I'm currently doing is hard-coding the Class.cpp file location in Dir2/CMakeLists.txt but that just doesn't scale when I've got a bunch of classes interacting together.

Setzer22
  • 1,589
  • 2
  • 13
  • 29
  • You can use the `FILE(GLOB ...)` action to gather a bunch of files with a particular extension. – πάντα ῥεῖ Sep 01 '14 at 16:18
  • But won't that work only inside of Dir2? I want to use the cpp file in Dir1. I specifically want not to have to specify all the files in the executable folder's CMakeLists but make each folder register the cpps it has. – Setzer22 Sep 01 '14 at 16:21
  • 1
    possible duplicate of [CMake - Automatically add all files in a folder to a target?](http://stackoverflow.com/questions/3201154/cmake-automatically-add-all-files-in-a-folder-to-a-target) – Marco A. Sep 01 '14 at 16:21
  • @Setzer22 You can use the `RELATIVE` option to specify whichever directory you want. What about looking into CMake's manual? – πάντα ῥεῖ Sep 01 '14 at 16:23
  • @πάντα ῥεῖ I'm not sure I understand what the relative function does. Are you sure that helps me in any way to define the source files for my executable from another folder? – Setzer22 Sep 01 '14 at 16:27
  • @Setzer22 You'll just create 2 sets of source file names and add them both to your `ADD_EXECUTABLE`. – πάντα ῥεῖ Sep 01 '14 at 16:36
  • Either I got the very fundamentals of CMake wrong or I'm not understanding what you're telling me at all. Could you please be more specific on what should I do? – Setzer22 Sep 01 '14 at 16:53
  • @Setzer22 I've posted an answer explaining what I mean in detail. – πάντα ῥεῖ Sep 01 '14 at 17:08

1 Answers1

23

Supposed you have a single CMakeLists.txt file at the Source directory, you'll create two variables using different file() commands

file(GLOB Dir1_Sources RELATIVE "Dir1" "*.cpp")
file(GLOB Dir2_Sources RELATIVE "Dir2" "*.cpp")

and add both sets generated by the file() commands to your target's source list:

add_executable(MyProgram ${Dir1_Sources} ${Dir2_Sources})

Alternatively you can place a CMakeLists.txt file under Dir1 and Dir2 (Main) looking as follows

Source
    |
    |_ CMakeLists.txt   
    |    > project(MyProgram)
    |    > cmake_minimum_required(VERSION 3.8)
    |    > add_subdirectory("Dir1")
    |    > add_subdirectory("Dir2")
    |
    |_ Dir1   
    |     |_ CMakeLists.txt   
    |         > file(GLOB Sources "*.cpp")
    |         > add_library(Dir1 STATIC ${Sources})
    |_ Dir2   
          |_ CMakeLists.txt   
              > file(GLOB Sources "*.cpp")
              > add_executable(MyProgram ${Sources})
              > target_link_libraries(MyProgram Dir1)

to add subdirectories as further (static) libraries linked to your main target.

starball
  • 20,030
  • 7
  • 43
  • 238
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • What I'm asking for is the line file(GLOB Dir1_Sources RELATIVE "Dir1" "*.cpp") to be in a different CMakeLists.txt file, the one in Dir1, not Source nor Dir2. But I see that's not the workflow with CMake as everyone in the internet seems to be insisting in doing everything on a single file. Yours is a nice trick anyway, thank you. – Setzer22 Sep 01 '14 at 17:30
  • @Setzer22 Yeah, of course this sample supposed that you have a single `CMakeLists.txt` at `Source` level. Well, though you could also place appropriate `CMakeLists.txt` files in the (non main) subdirectories to build libraries, and add these with [`add_subdirectory()`](http://www.cmake.org/cmake/help/v3.0/command/add_subdirectory.html), but as you mentioned that's not the usual way to just gather from sources. – πάντα ῥεῖ Sep 01 '14 at 17:41
  • @Setzer22 I've added another sample for the mentioned alternative solution. – πάντα ῥεῖ Sep 01 '14 at 18:10
  • 1
    I made a few edits to please CLion. Importantly, `add_executable` needs to come before `target_link_libraries`, otherwise cmake will complain. – qed Aug 25 '17 at 21:39
  • 1
    Not sure why *RELATIVE* is used here, but line `file(GLOB Dir1_Sources RELATIVE "Dir1" "*.cpp")` being executed in `CMakeLists.txt`, **doesn't collect** sources in `Dir1/` subdirectory. Correct call would be `file(GLOB Dir1_Sources "Dir1/*.cpp")`. – Tsyvarev May 12 '18 at 10:28