CMake:链接包含在类外定义的全局函数的库

时间:2015-03-09 12:52:28

标签: c++ cmake

尝试使用CMake从Ubuntu SDK编译我的项目时出现此错误:

13:38:31: Starting: "/usr/bin/make" 
Scanning dependencies of target LTexture
[ 20%] Building CXX object CMakeFiles/LTexture.dir/libs/ltexture.cpp.o
/home/vitimiti/devel/PokemonCrystalRemastered/libs/ltexture.cpp: In member function 'bool LTexture::loadFromFile(std::string)':
/home/vitimiti/devel/PokemonCrystalRemastered/libs/ltexture.cpp:61:66: warning: passing NULL to non-pointer argument 3 of 'SDL_Surface* SDL_ConvertSurfaceFormat(SDL_Surface*, Uint32, Uint32)' [-Wconversion-null]
                 loadedSurface, SDL_PIXELFORMAT_RGBA8888, NULL);
                                                              ^
Linking CXX shared library libLTexture.so
[ 20%] Built target LTexture
Scanning dependencies of target constants
[ 40%] Building CXX object CMakeFiles/constants.dir/libs/constants.cpp.o
Linking CXX shared library libconstants.so
[ 40%] Built target constants
Scanning dependencies of target globals
[ 60%] Building CXX object CMakeFiles/globals.dir/libs/globals.cpp.o
Linking CXX shared library libglobals.so
[ 60%] Built target globals
Scanning dependencies of target MapMaker
[ 80%] Building CXX object CMakeFiles/MapMaker.dir/mapmaker.cpp.o
Linking CXX executable MapMaker
CMakeFiles/MapMaker.dir/mapmaker.cpp.o: In function `main':
mapmaker.cpp:(.text+0x48): undefined reference to `init(std::string)'
collect2: error: ld returned 1 exit status
CMakeFiles/MapMaker.dir/build.make:85: recipe for target 'MapMaker' failed
CMakeFiles/Makefile2:96: recipe for target 'CMakeFiles/MapMaker.dir/all' failed
Makefile:76: recipe for target 'all' failed
make[2]: *** [MapMaker] Error 1
make[1]: *** [CMakeFiles/MapMaker.dir/all] Error 2
make: *** [all] Error 2
13:38:37: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project PokemonCrystalRemastered (kit: Desktop)
When executing step 'Make'

CMakeLists.txt文件如下所示:

project(PokemonCrystalRemastered)
cmake_minimum_required(VERSION 3.0.2)

add_definitions(
    -std=c++11
)

# The version number.
set(${PROJECT_NAME}_VERSION_MAJOR 0)
set(${PROJECT_NAME}_VERSION_MINOR 1)

# Configure a header file to pass some of the CMake settings to the source code
configure_file(
    ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.h.in
    ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.h
)

# Add the binary tree to the search path for include files so that we will find
# ${PROJECT_NAME}Config.h
include_directories(${PROJECT_BINARY_DIR})

# The game itself
add_executable(${PROJECT_NAME}
    main.cpp
)
# The map maker
add_executable(MapMaker
    mapmaker.cpp
)

# Project libraries
include_directories(${PROJECT_SOURCE_DIR}/libs)

add_library(LTexture SHARED
    libs/ltexture.cpp
)
add_library(globals SHARED
    libs/globals.cpp
)
add_library(constants SHARED
    libs/constants.cpp
)

target_link_libraries(${PROJECT_NAME}
    ${constants}
    ${globals}
    ${LTexture}
)
target_link_libraries(MapMaker
    ${constants}
    ${globals}
    ${LTexture}
)

add_dependencies(globals constants)
add_dependencies(${PROJECT_NAME} globals)
add_dependencies(MapMaker globals)
add_dependencies(${PROJECT_NAME} LTexture)
add_dependencies(MapMaker LTexture)

# SDL2 libraries
include(FindPkgConfig)

pkg_search_module(SDL2 REQUIRED sdl2)
pkg_search_module(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)
pkg_search_module(SDL2TTF REQUIRED SDL2_ttf>=2.0.0)
pkg_search_module(SDL2MIXER REQUIRED SDL2_mixer>=2.0.0)

include_directories(${SDL2_INCLUDE_DIRS}
    ${SDL2IMAGE_INCLUDE_DIRS}
    ${SDL2TTF_INCLUDE_DIRS}
    ${SDL2MIXER_INCLUDE_DIRS}
)
target_link_libraries(${PROJECT_NAME}
    ${SDL2_LIBRARIES}
    ${SDL2IMAGE_LIBRARIES}
    ${SDL2TTF_LIBRARIES}
    ${SDL2MIXER_LIBRARIES}
)

constants.h看起来像:

#ifndef CONSTANTS_H
#define CONSTANTS_H

extern const int SCREEN_WIDTH;
extern const int SCREEN_HEIGHT;

#endif // CONSTANTS_H

constants.cpp看起来像:

#include "constants.h"

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

globals.h看起来像:

#include <SDL2/SDL.h>

#include <string>

using namespace std;

// The global window and renderer
extern SDL_Window *gWindow;
extern SDL_Renderer *gRenderer;

// Initiate SDL and stuff
bool init(string windowTitle);
// Load the needed media in the start
bool loadMedia();
// Close SDL and free
void close();

globals.cpp看起来像:

#include <stdio.h>

#include <SDL2/SDL_image.h>

#include "constants.h"
#include "globals.h"

SDL_Window *gWindow = NULL;
SDL_Renderer *gRenderer = NULL;

bool init(string windowTitle)
{
    // Initialize success flag
    bool success = true;

    // Initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        printf("[E] Unable to initialize: %s\n", SDL_GetError());
        success = false;
    }
    else
    {
        // Set texture filtering to linear
        if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
            printf("[W] Linear texture filtering not enabled\n");

        // Create the window
        gWindow = SDL_CreateWindow(windowTitle.c_str(), SDL_WINDOWPOS_CENTERED,
                                   SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
                                   SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        // If the window is null
        if (gWindow == NULL)
        {
            printf("[E] Unable to create window: %s", SDL_GetError());
            success = false;
        }
        else
        {
            // Create the renderer for the window
            gRenderer = SDL_CreateRenderer(gWindow, -1,
                                           SDL_RENDERER_ACCELERATED |
                                           SDL_RENDERER_PRESENTVSYNC);
            // If the renderer is null
            if (gRenderer == NULL)
            {
                printf("[E] Unable to create renderer: %s\n", SDL_GetError());
                success = false;
            }
            else
            {
                // Initialize renderer color
                SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255);

                // Initialize the PNG loading
                int imgFlags = IMG_INIT_PNG;
                if (!(IMG_Init(imgFlags) & imgFlags))
                {
                    printf("[E] Unable to initialize SDL_image: %s\n",
                           IMG_GetError());
                    success = false;
                }
            }
        }
    }

    // Return the success flag
    return success;
}

现在的主要功能如下:

#include <stdio.h>

#include "libs/globals.h"

int main(int argc, char *argv[])
{
    if (!init("Pokémon Crystal Remastered Map Maker"))
    {
        printf("[E] Unable to initialize program\n");
        return 1;
    }

    return 0;
}

在两个可执行文件中。即使有两个可执行文件,编译甚至没有到达第二个,在地图制作者已经失败。

我确实知道两个可执行文件都添加了#include "libs/globals.h",以便在两个文件中找到bool init(std::string windowTitle),我找不到让它们相互链接的方法。我已经尝试添加依赖项,如文件中所示,但仍然无法正常工作。我该怎么办?

免责声明:这是一个个人项目,不会发布,这是一种培训方法和挑战,不会侵犯版权。

1 个答案:

答案 0 :(得分:0)

您目前正在尝试链接到名为constantsglobalsLTexture的变量中的库(使用${}表示法),这些变量是空的。以下应该可以解决问题:

add_library(LTexture SHARED
    libs/ltexture.cpp
)
add_library(globals SHARED
    libs/globals.cpp
)
add_library(constants SHARED
    libs/constants.cpp
)

target_link_libraries(${PROJECT_NAME}
    constants # ${constants} is empty 
    globals   # ${globals} is empty
    LTexture  # ${LTexture} is empty
)
target_link_libraries(MapMaker
    constants # ${constants} is empty
    globals   # ${globals} is empty
    LTexture  # ${LTexture} is empty
)