# [solved] Brauch mal cmake-Einstiegshilfe: Linking-Problem

## musv

Guten Morgen. 

Ich versuch mir seit kurzem mal cmake zu Gemüte zu führen, scheiter aber schon bei einem einfachen Linking-Problem. Dazu hab ich ein Hello-World-Projekt gebastelt und versuch das Teil jetzt zum Laufen zu kriegen. 

Verzeichnisstruktur:

```
./CMakeLists.txt

./includes

./src

./src/main.cpp

./src/CMakeLists.txt

./src/klasse.cpp

./src/klasse.h

./build

./bin
```

Source-Code:

```
#include <iostream>

#include "klasse.h"

int main()

{

   std::cout << "Main" << std::endl;

   Klasse * k = new Klasse();

   delete k;

   return 0;

}
```

```
#ifndef KLASSE_H

#define KLASSE_H

class Klasse

{

   public:

      Klasse();

      virtual ~Klasse();

};

#endif
```

```
#include "klasse.h"

#include <iostream>

Klasse::Klasse()

{

   std::cout << "Klasse Konstruktor" << std::endl;

}

Klasse::~Klasse()

{

   std::cout << "Klasse Destruktor" << std::endl;

}
```

CMake-Configs:

```
cmake_minimum_required(VERSION 2.8)

project(hello)

set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)

add_subdirectory(src)
```

Zu erstellendes Binary soll hello heißen und im bin-Verzeichnis abgelagert werden. 

Die zu compilierenden Dateien befinden sich in src. Die Headerdateien will ich später noch nach includes auslagern.

```
add_executable(hello main.cpp)
```

main.cpp ist der Einstiegspunkt, mit dem das Binary hello gebaut werden soll.

Build-Prozess:

Und damit kommen wir zu meinem Problem. 

```
cd build

cmake ..

-> Ausgabe:

-- The C compiler identification is GNU 4.7.2

-- The CXX compiler identification is GNU 4.7.2

-- Check for working C compiler: /usr/bin/cc

-- Check for working C compiler: /usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Check for working CXX compiler: /usr/bin/c++

-- Check for working CXX compiler: /usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- Configuring done

-- Generating done

-- Build files have been written to: /home/blubb/Programmierung/cmake_hello/build

make

-> Ausgabe:

Scanning dependencies of target hello

[100%] Building CXX object src/CMakeFiles/hello.dir/main.cpp.o

Linking CXX executable ../../bin/hello

CMakeFiles/hello.dir/main.cpp.o: In function `main':

main.cpp:(.text+0x38): undefined reference to `Klasse::Klasse()'

collect2: Fehler: ld gab 1 als Ende-Status zurück

make[2]: *** [../bin/hello] Fehler 1

make[1]: *** [src/CMakeFiles/hello.dir/all] Fehler 2

make: *** [all] Fehler 2
```

Warum? Was fehlt mir?Last edited by musv on Fri Jan 11, 2013 12:26 pm; edited 1 time in total

----------

## firefly

du musst bei add_executable alle sourcen angeben...

----------

## musv

Hast Recht. Es klappt. 

Eigentlich war ich davon ausgegangen, dass cmake das irgendwie aus dem Quellcode und den darin angegebenen Abhängigkeiten selbst auf die Reihe bekommen. Aber nun gut, es funktioniert. 

Danke

----------

## franzf

 *musv wrote:*   

> Eigentlich war ich davon ausgegangen, dass cmake das irgendwie aus dem Quellcode und den darin angegebenen Abhängigkeiten selbst auf die Reihe bekommen. Aber nun gut, es funktioniert.

 

Kann GCC allein durch Übergabe einer main.cpp alle Abhähngigkeiten _selbständig_ ermitteln? Nö  :Wink: 

Das Problem sollte recht komplex sein, cmake müsste dafür einen eigenen Parser für ALLE unterstützten Sprachen mitbringen. Größere Projekte würden dadurch allein fürs Makefile erzeugen ziemlich lange brauchen.

----------

## AmonAmarth

Kleiner Tipp um nicht immer alle Dateien einzeln in die CMakeLists eintragen zu müssen:

```
file(GLOB Sources ${PROJECT_SOURCE_DIR}/src/*.cpp)

add_executable(Hello ${Sources}
```

----------

## franzf

Globben würd ich nicht, weil man damit auch auf die Schnauze fallen kann. Z.B. wenn man eine Klasse umschreibt/splittet/... und die Implementierung in neue .cpp-Dateien packt -> multiple definition, wenn man nicht aufpasst. Und wenn man sich (dank GLOB) nicht mehr ums CMakeLists.txt kümmert, erinnert man sich am Ende gar nicht mehr daran...

----------

## AmonAmarth

 *franzf wrote:*   

> Globben würd ich nicht, weil man damit auch auf die Schnauze fallen kann. Z.B. wenn man eine Klasse umschreibt/splittet/... und die Implementierung in neue .cpp-Dateien packt -> multiple definition, wenn man nicht aufpasst. Und wenn man sich (dank GLOB) nicht mehr ums CMakeLists.txt kümmert, erinnert man sich am Ende gar nicht mehr daran...

 

Dann wird der compiler meckern, entweder wegen missing implementation oder double definition. Dann muss man einfach nur einmal cmake neu ausführen und fertig.

EDIT: oder meinst du, wenn man die implementierung von A.cpp nach B.cpp kopiert und nicht verschoben hat? Genau sowas sollte man meiner meinung nach noch weniger machen...

----------

