tl;dr the questions are at the bottom.
I am a developer trying something new – my last poison is c++. As I am spending half of my time on my linux laptop and the other half on Win XP PC, I tried to find a way to create basic, barebone project, using good c++ practices (well, I don’t know them from experience, I just read about them). Right now my project almost works while using cmake . && make on linux (it works when header and source files are in the same folder, fails when I separate them to include / src folders). I am using nuwen’s distribution of mingw on windows (and I know that the toolchain is working, it compiles projects from within Eclipse without any problems).
My project directory looks like this:
engine
|
|- main
|
|- include
|
|- App.h
|- CMakeLists.txt (2)
|- src
|
|- main.cc
|- App.cc
|- CMakeLists.txt (3)
|- CMakLists.txt (1)
The contents of the files are very simple (I will remove the include guards, etc for clarity)
App.h:
class App {
public:
App();
int onExecute();
};
App.cc:
#include <iostream>
#include "App.h"
App::App() {
}
int App::onExecute() {
std::cout << "inside app.." << '\n';
return 0;
}
main.cc:
#include <iostream>
#include "App.h"
using namespace std;
int main(int argc, char* argv[]) {
App a;
a.onExecute();
std::cout << "inside main.." << '\n';
}
CMakeLists.txt (1) – the main one:
cmake_minimum_required (VERSION 2.6)
set (CMAKE_CXX_COMPILER "g++")
project (gameengine)
add_definitions ( "-Wall -ansi -pedantic")
add_subdirectory (${CMAKE_SOURCE_DIR}/main/include)
add_subdirectory (${CMAKE_SOURCE_DIR}/main/src)
add_executable (engine ${CMAKE_SOURCE_DIR}/main/src/main.cc)
target_link_libraries (engine Application)
CMakeLists.txt (2) – inside the include directory
add_library (Application App)
set_target_properties (Application PROPERTIES LINKER_LANGUAGE CXX)
CMakeLists.txt (3) – inside the src directory
include_directories (../include)
And this is as far as I got – with some changes (i.e. moving App.cc to the include directory) the whole thing compiles and runs fine on linux – but I can’t get the mingw generator to work on Win XP. I hand tuned the CMAKE_MAKE_PROGRAM in the file CMakeCache.txt to point to the proper make.exe (I know that this should be defined as a system variable but as I am working on many different PC’s, I don’t want to leave junk after me).
My questions are:
1) what are the guidelines for writing multiplatform CMakeLists.txt file (which will work independly of the os and the location of the project files), which preferably will allow me to easy swich my project configuration from one os the other one?
2) how can I address the error of not finding the header file (make gives: (…)\engine\main\src\main.cc:2:17: fatal error: App.h: No such file or directory) ?
Thank you for your time and help.
Well, I’m certainly no expert, but I can share my 10-month experience with a cross-platform cmake-based project.
Right off the bat I think you really should be using out of source builds. This means that you don’t run cmake in the same directory where your code is; instead, you create a new folder, e.g.
engine/buildand runcmake ../mainfrom there. This way you don’t clobber your source files with cmake stuff, such as CMakeCache.txt etc. There are even some macros you can use to forbid your users from doing in-source builds.I also find it useful to create a set of macro files to help set compiler options for different platforms. Here at work we have macros such as
ADD_GCC_FLAGorADD_MSVC_FLAGwhich check the current compiler and add flags accordingly.I think it is good practice to have a single
.cmakefile which concentrates all your project configurations in one place. At work all ourCMakeLists.txtstart withinclude( ../cmake/configs.cmake ). This file sets all sorts of options, such as standard include directories, default compiler flags etc.To assuage your problem with include directories, I suggest you use absolute rather than relative paths in your source files. Define a standard include directory, for instance
engine/main/includeand always#includefiles relative to that path. In your example, if you wanted to includeengine/main/include/somefolder/header.h, you’d write#include <somefolder/header.h>(using<>instead of quotes tells the C++ preprocessor to skip the current directory when looking for the file).There are a number of issues with your cmake layout, but the reason you were getting that error is because you need to call
include_directoriesinCMakeLists.txt (1)as well.Besides that, your other
CMakeLists.txtfiles have problems too. InCMakeLists.txt (2), the arguments toadd_libraryare wrong; it should be../src/App.cc, otherwise you’re just adding an empty library. And you don’t need thatset_target_propertieseither, at least not if you got theadd_libraryarguments right. You also need ainclude_directorycall in that sameCMakeLists.txtthat’s adding the library; putting it in(3)doesn’t really do anything.Actually, you don’t need a
CMakeLists.txtfile in theincludedirectory, since there’s nothing to build there. It’s better to put theadd_librarycall inCMakeLists.txt (3), right after callinginclude_directories.I hope this clears some of your doubts.