2

To begin with, I'm new to CMake.

Folder structure

root_project
  |─── CMakeLists.txt
  |─── build
  |─── Project 1
  |      |─── build
  |      |      |─── Debug
  |      |      └─── Release
  |      |─── CMakeLists.txt
  |      |─── source
  |      |      └─── include
  |      |─── resource
  |      └─── header
  └─── Project 2
         |─── build
         |      |─── Debug
         |      └─── Release
         |─── source
         |      |─── CMakeLists.txt
         |      └─── include
         |─── resource
         └─── header

CMake files

The CMakeLists.txt for the root_project:

# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2 FATAL_ERROR)

# Project's name
project("RootProject X")

IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
    message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt.")
ENDIF()

OPTION(BUILD_TESTS "Decides whether the unit tests will be built." ON)

# C/C++ languages required.
enable_language(C)
enable_language(CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Only allow 64bit architecture
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
    # 64bit
    message(STATUS "Compiling for x86-64 platform. Proceeding...")
ELSEIF(CMAKE_SIZEOF_VOID_P EQUAL 4)
    # 32bit
    message(FATAL_ERROR "Compiling for x86 platform. This is not supported. Aborting...")
ELSE()
    # unidentified architecture
    message(FATAL_ERROR "Running on unidentified architecture. This is not supported. Aborting...")
ENDIF()

# Abort when OpenGL is not found
FIND_PACKAGE(OpenGL 4.5 REQUIRED)

IF(NOT VULKAN_FOUND)
    message(WARNING "Could not find Vulkan library.")
ENDIF()

# Add the modules
add_subdirectory("Project 1")
add_subdirectory("Project 2")

The CMakeLists for Project 1:

# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2 FATAL_ERROR)

project("Project 1")

# Set the version number of the project here
set(VERSION_MAJOR "0")
set(VERSION_MINOR "1")
set(VERSION_PATCH "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})

find_package(OpenGL 4.5 REQUIRED)

include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sources/third-party-include/)
link_libraries(${OPENGL_gl_LIBRARY})
add_definitions(${OpenGL_DEFINITIONS})

#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sources/include/)

# ToDo: Testing
set(HEADERS
    ${CMAKE_CURRENT_SOURCE_DIR}/sources/include/Engine.h
)

set(SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/source/Engine.cpp
)

source_group(headers FILES ${HEADERS})
source_group(sources FILES ${SOURCES})

if(WIN32)
# currently add_executable for testing purpose
add_executable("Project 1" WIN32
    #${HEADERS}
    ${SOURCES}
)
ELSEIF(UNIX AND NOT APPLE)
add_library("Project 1"
    ${HEADERS}
    ${SOURCES}
)
ELSE()
# The system is not supported
message(FATAL_ERROR "System not supported.")
ENDIF()

target_link_libraries(DarkEngine ${OPENGL_gl_LIBRARY})

The CMakeLists for Project 2:

# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2 FATAL_ERROR)

project("Project 2")

# Set the version number of the project here
set(VERSION_MAJOR "0")
set(VERSION_MINOR "1")
set(VERSION_PATCH "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})

set(HEADERS

)

set(SOURCES

)

source_group(headers FILES ${HEADERS})
source_group(sources FILES ${SOURCES})

add_executable("Project 2" WIN32
    ${HEADERS}
    ${SOURCES}
)

target_link_libraries("Project 2" "Project 1")

Question/Problem

Note: I am trying to achieve an out-of-source build where Project 1 is an Engine which is used from Project 2.

Commands I run under build of root_project: cmake .. -G "Visual Studio 15 2017 Win64"

  • Project 2 doesn't link against Project 1
  • Project 2 doesn't show up in VS 2017
  • My own header files under /include for Project 1 will be shown in External Dependencies in VS 2017 instead of source
ShadowDragon
  • 2,238
  • 5
  • 20
  • 32
  • In CMake<->VS terms project=solution and target=project – tambre Jul 29 '17 at 12:06
  • Though I'd like to mention, that I like the quality of the question. Keep up the good work! :) – tambre Jul 29 '17 at 12:14
  • I always try to structure my posts to get a higher quality. So with your comment, what should I actually do to fix my problem? – ShadowDragon Jul 29 '17 at 15:34
  • Just from looking at it: How would you link (Project 2) against an executable (Project 1)? And CMake should have given you an warning or error that Project 2 does not contain any sources (which is probably why it won't show up). – Florian Jul 29 '17 at 19:02
  • That's why I wrote the comment above it. Normally Project 1 is not an executable and will be created with add_library like under Linux. Yeah, it gave me that warning, but when creating a new project with CMake for an IDE, how would you create than files? Manually outside of the IDE, this would sound a bit odd to me. – ShadowDragon Jul 29 '17 at 20:39
  • @ShadowDragon Outside of the IDE is the least troublesome, if you're using VS. Modifying things inside the generated solution will have no effect on your CMake files and it may mess up your folder structure. VS15's CMake support might be what you're looking for though. – tambre Jul 30 '17 at 16:37

1 Answers1

1

Turning my comment into an answer

You just need to specify sources for your Project 2 target.

I've given you example a try and CMake gives you an configuration error (which is probably why it won't show up/doesn't rewrite the solution/project files, if you add the second project):

CMake Error at CMakeLists.txt:23 (add_executable):
   add_executable called with incorrect number of arguments, no sources provided

And yes, if you add e.g. a not yet existing src/main.cpp to SOURCES you will get:

CMake Error at CMakeLists.txt:23 (add_executable):
  Cannot find source file:

    src/main.cpp

  Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx

So the workflow in CMake is always to first create the source file and then add to your CMakeLists.txt. With an IDE like VS you could just add a new item to your project (like you would do for non-generated projects) and then add it to your CMakeLists.txt file.

For some of my projects I've created a check_and_create_source() function called inside overwritten add_executable() calls, but using it for some years I can now say there is no real benefit in that approach. You still need to run a ZERO_CHECK build to get the empty files created/before you can start (and you get confused when you mistyped an inclusion for an existing source file).

And I personally don't like the globbing alternative (see Why is cmake file GLOB evil? and CMake/Ninja attempting to compile deleted `.cpp` file)

Florian
  • 39,996
  • 9
  • 133
  • 149
  • @ShadowDragon Can you please get a little more specific about the problems you got, it seemed to work when I tested it with sources/headers for "Project 2"? I just encountered that "Project 2" was not accepted by CMake as "being a reserved name". So I had to rename to e.g. "Project2". For the last point, you have to give all headers you want to be in the IDE project as sources, otherwise they will only be shown as "external dependencies". – Florian Aug 02 '17 at 20:44
  • **To point 3:** So I have to add them explicitly to the `add_executable` command? How can I list those headers without putting the full relative path in the CMakeLists.txt file. For example I just have to write `Engine.h` instead of `sources/include/Engine.h`. Would also be nice to know this for the source files in generally. **To point 1:** VS for example can't include any files from Project 1 in Project 2. Note: Project 2 got only a main.cpp with no code in it, so it shows up in VS. – ShadowDragon Aug 05 '17 at 16:00