8

以下のプロジェクト構造は単純化された例です。問題を再現するために、最小限のファイル数にまとめようとしました。

.
├── CMakeLists.txt
├── subdir1
│   ├── CMakeLists.txt
│   └── subsubdir1
│       ├── CMakeLists.txt
│       ├── Example.cpp
│       └── Example.h
└── subdir2
    ├── CMakeLists.txt
    ├── main.cpp
    └── subsubdir1
        ├── CMakeLists.txt
        ├── ExampleCreator.cpp
        └── ExampleCreator.h

./CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(test)

macro(add_sources)
    file (RELATIVE_PATH _relPath "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
    foreach (_src ${ARGN})
        if (_relPath)
            list (APPEND SRCS "${_relPath}/${_src}")
        else()
            list (APPEND SRCS "${_src}")
        endif()
    endforeach()
    if (_relPath)
        # propagate SRCS to parent directory
        set (SRCS ${SRCS} PARENT_SCOPE)
    endif()
endmacro()

add_subdirectory(subdir1)
add_subdirectory(subdir2)

add_executable(test ${SRCS})

subdir1 / CMakeLists.txt

add_subdirectory(subsubdir1)

subdir1 / subsubdir1 / CMakeLists.txt

add_sources(Example.cpp)

subdir1 / subsubdir1 / Example.h

#ifndef EXAMPLE_H
#define EXAMPLE_H

class Example
{
public:
    Example();
    virtual ~Example();
};

#endif

subdir1 / subsubdir1 / Example.cpp

#include <stdio.h>
#include "Example.h"

Example::Example()
{
    printf("Inside Example constructor\n");
}

Example::~Example()
{
}

subdir2 / CMakeLists.txt

add_subdirectory(subsubdir1)
add_sources(main.cpp)

subdir2 / main.cpp

#include "subsubdir1/ExampleCreator.h"

int main(int argc, char** argv)
{
    ExampleCreator creator;
    return 0;
}

subdir2 / subsubdir1 / CMakeLists.txt

add_sources(ExampleCreator.cpp)

subdir2 / subsubdir1 / ExampleCreator.h

#ifndef EXAMPLE_CREATOR_H
#define EXAMPLE_CREATOR_H

class ExampleCreator
{
public:
    ExampleCreator();
    virtual ~ExampleCreator();
};

#endif

subdir2 / subsubdir1 / ExampleCreator.cpp

#include "ExampleCreator.h"
#include "../../subdir1/subsubdir1/Example.h"

ExampleCreator::ExampleCreator()
{
    Example* ex1 = new Example();
}

ExampleCreator::~ExampleCreator()
{
}

これが、CMakeが依存関係を処理する方法についての本当に単純な理解の欠如であることを願っています。これはエラーなしでコンパイルされますが、リンク中に失敗します。以下のmake出力は、それExample.cppがコンパイルされていないことを示しており、その理由がわかりません。

user>:~/src/test/build$ make
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/subdir2/subsubdir1/ExampleCreator.cpp.o
[100%] Building CXX object CMakeFiles/test.dir/subdir2/main.cpp.o
Linking CXX executable test
CMakeFiles/test.dir/subdir2/subsubdir1/ExampleCreator.cpp.o: In function `ExampleCreator::ExampleCreator()':
ExampleCreator.cpp:(.text+0x2b): undefined reference to `Example::Example()'
collect2: ld returned 1 exit status
make[2]: *** [test] Error 1
make[1]: *** [CMakeFiles/test.dir/all] Error 2
make: *** [all] Error 2

私が知る限り、すべてのソースがSRCSルートCMakeLists.txtファイルの変数に追加されています。では、なぜExample.cppコンパイルされないのですか?またはリンクされていますか?

4

1 に答える 1

6

ディレクトリsubdir1はバイナリを生成しません。これを追加:

project(Example)
add_library(Example Example.cpp)

あなたの代わりにadd_sources。この後、それを使用してリンクするプロジェクトに指示する必要があります。

TARGET_LINK_LIBRARIES(subdir2 Example)

名前が異なる場合は、これらのコマンドの機能について自分で文書化してください。

于 2012-10-24T20:33:25.953 に答える