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.
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?
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/build
and run cmake ../main
from 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_FLAG
or ADD_MSVC_FLAG
which check the current compiler and add flags accordingly.
I think it is good practice to have a single .cmake
file which concentrates all your project configurations in one place. At work all our CMakeLists.txt
start with include( ../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/include
and always #include
files relative to that path. In your example, if you wanted to include engine/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).
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) ?
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_directories
in CMakeLists.txt (1)
as well.
Besides that, your other CMakeLists.txt
files have problems too. In CMakeLists.txt (2)
, the arguments to add_library
are wrong; it should be ../src/App.cc
, otherwise you're just adding an empty library. And you don't need that set_target_properties
either, at least not if you got the add_library
arguments right. You also need a include_directory
call in that same CMakeLists.txt
that's adding the library; putting it in (3)
doesn't really do anything.
Actually, you don't need a CMakeLists.txt
file in the include
directory, since there's nothing to build there. It's better to put the add_library
call in CMakeLists.txt (3)
, right after calling include_directories
.
I hope this clears some of your doubts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With