title: CMake - Custom Freetype library doesn't link
body: <p>I'm trying to make a custom C++ library which includes a wrapper class for FreeType2 font rendering. Here's the header file for the wrapper class:</p>
  
  <pre><code>#ifndef FREETYPEFONT_HPP
  #define FREETYPEFONT_HPP
  
  #include &lt;string&gt;
  
  #include &lt;ft2build.h&gt;
  #include FT_FREETYPE_H
  
  #include &lt;GL/glew.h&gt;
  
  namespace g4tk
  {
    struct GlyphData
    {
      float ax;
      float ay;
      float left;
      float top;
      float width;
      float rows;
      float tx;
    };
  
    class FreeTypeFont
    {
      public:
        void Initialize(std::string font_file, int font_size);
        void RenderText(std::string str, float x, float y, float z, float sx, float sy);
        void RenderInteger(int number, float x, float y, float z, float sx, float sy);
        void RenderCurrency(float amount, float x, float y, float z, float sx, float sy);
        float CalcWidth(std::string str, float sx);
        float CalcAveHeight(std::string str, float sy);
      private:
        // FreeType-specific variables
        FT_Library library;
        FT_Face face;
        FT_Bool use_kerning;
        FT_UInt previous;
        // Glyph and atlas variables
        int atlas_width;
        int atlas_height;
        GlyphData Glyphs[128];
        // OpenGL variables
        GLuint atlas_texture;
        GLuint glyph_vao, glyph_vbo[2];
    };
  }
  
  #endif
  </code></pre>
  
  <p>And the main file:</p>
  
  <pre><code>#include "FreeTypeFont.hpp"
  
  #include &lt;iostream&gt;
  #include &lt;sstream&gt;
  #include &lt;vector&gt;
  
  #include &lt;cmath&gt;
  
  #include &lt;GL/glew.h&gt;
  
  namespace g4tk
  {
    void FreeTypeFont::Initialize(std::string font_file, int font_size)
    {
      // Initialize FreeType library and load face 
      int error = FT_Init_FreeType(&amp;library);
      if(error)
      {
        std::cout &lt;&lt; "An error occurred during library initialization!\n";
      }
      error = FT_New_Face(library, font_file.c_str(), 0, &amp;face);
      if(error == FT_Err_Unknown_File_Format)
      {
        std::cout &lt;&lt; "The font file could be opened and read, but it appears " &lt;&lt; 
        "that its font format is unsupported.\n";
      }
      else if(error)
      {
        std::cout &lt;&lt; "Another error code means that the font file could not be " &lt;&lt;
        "opened or read, or that it is broken.\n";
      }
      else std::cout &lt;&lt; "Font file sucessfully loaded!\n";
      use_kerning = FT_HAS_KERNING(face);
      FT_Set_Pixel_Sizes(face, 0, font_size);
      FT_GlyphSlot g = face-&gt;glyph;
  
      // Get atlas dimensions
      atlas_width = atlas_height = 0;
      for(int i = 32; i &lt; 128; i++)
      {
        if(FT_Load_Char(face, i, FT_LOAD_RENDER))
        {
          fprintf(stderr, "Loading character %c failed!\n", i);
          continue;
        }
        atlas_width += g-&gt;bitmap.width;
        atlas_height = std::max(atlas_height, int(g-&gt;bitmap.rows));
      }
  
      // Initialize texture
      glActiveTexture(GL_TEXTURE0);
      glGenTextures(1, &amp;atlas_texture);
      glBindTexture(GL_TEXTURE_2D, atlas_texture);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, atlas_width, atlas_height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
  
      // Load individual glyphs
      int x_offset = 0;
      FT_Vector delta;
      for(int i = 32; i &lt; 128; i++)
      {
        if(FT_Load_Char(face, i, FT_LOAD_RENDER))
        {
          fprintf(stderr, "Loading character %c failed!\n", i);
          continue;
        }
        Glyphs[i].ax = g-&gt;advance.x &gt;&gt; 6;
        Glyphs[i].ay = g-&gt;advance.y &gt;&gt; 6;
        Glyphs[i].left = g-&gt;bitmap_left;
        Glyphs[i].top = g-&gt;bitmap_top;
        Glyphs[i].width = g-&gt;bitmap.width;
        Glyphs[i].rows = g-&gt;bitmap.rows;
        Glyphs[i].tx = float(x_offset) / float(atlas_width);
        glTexSubImage2D(GL_TEXTURE_2D, 0, x_offset, 0, g-&gt;bitmap.width, g-&gt;bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g-&gt;bitmap.buffer);
        x_offset += Glyphs[i].width;
      }
  
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  
      GLfloat vertex[] = {0.0f, 0.0f, 0.0f};
      GLfloat uv[] = {0.0f, 0.0f};
  
      glGenVertexArrays(1, &amp;glyph_vao);
      glBindVertexArray(glyph_vao);
  
      glGenBuffers(2, glyph_vbo);
  
      glBindBuffer(GL_ARRAY_BUFFER, glyph_vbo[0]);
      glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_DYNAMIC_DRAW);
  
      GLuint VertexAttributeID = 0;
      glVertexAttribPointer(VertexAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);
      glEnableVertexAttribArray(VertexAttributeID);
  
      glBindBuffer(GL_ARRAY_BUFFER, glyph_vbo[1]);
      glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_DYNAMIC_DRAW);
  
      GLuint UvAttributeID = 1;
      glVertexAttribPointer(UvAttributeID, 2, GL_FLOAT, GL_FALSE, 0, 0);
      glEnableVertexAttribArray(UvAttributeID);
  
      glBindVertexArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindTexture(GL_TEXTURE_2D, 0);
    }
  
    void FreeTypeFont::RenderText(std::string str, float x, float y, float z, float sx, float sy)
    {
      const char * text = str.c_str();
      float x2, y2, w, h;
      std::vector&lt;GLfloat&gt; vertex, uv;
      previous = 0;
      FT_Vector delta;
      for(const char *p = text; *p; p++)
      {
        // Retrieve kerning distance and move pen position
        if(use_kerning &amp;&amp; previous &amp;&amp; *p)
        {
          FT_Get_Kerning(face, previous, *p, 0, &amp;delta);
          x += (delta.x &gt;&gt; 6);
        }
  
        x2 = x + Glyphs[*p].left * sx;
        y2 = -y - Glyphs[*p].top * sy;
        w = Glyphs[*p].width * sx;
        h = Glyphs[*p].rows * sy;
  
        GLfloat v[] = {
          x2, -y2, z,
          x2+w, -y2, z,
          x2, -y2-h, z,
          x2+w, -y2, z,
          x2, -y2-h, z,
          x2+w, -y2-h, z
        };
        GLfloat u[] = {
          Glyphs[*p].tx, 0.0f,
          Glyphs[*p].tx + Glyphs[*p].width/atlas_width, 0.0f,
          Glyphs[*p].tx, Glyphs[*p].rows/atlas_height,
          Glyphs[*p].tx + Glyphs[*p].width/atlas_width, 0.0f,
          Glyphs[*p].tx, Glyphs[*p].rows/atlas_height,
          Glyphs[*p].tx + Glyphs[*p].width/atlas_width, Glyphs[*p].rows/atlas_height
        };
  
        vertex.insert(vertex.end(), v, v+18);
        uv.insert(uv.end(), u, u+12);
  
        x += Glyphs[*p].ax * sx;
        y += Glyphs[*p].ay * sy;
        previous = *p;
      }
  
      glActiveTexture(GL_TEXTURE0);
      glBindTexture(GL_TEXTURE_2D, atlas_texture);
      glBindVertexArray(glyph_vao);
      glBindBuffer(GL_ARRAY_BUFFER, glyph_vbo[0]);
      glBufferData(GL_ARRAY_BUFFER, sizeof(float)*vertex.size(), &amp;vertex[0], GL_DYNAMIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER, glyph_vbo[1]);
      glBufferData(GL_ARRAY_BUFFER, sizeof(float)*uv.size(), &amp;uv[0], GL_DYNAMIC_DRAW);
  
      glDrawArrays(GL_TRIANGLES, 0, 6*strlen(text));
    }
  
    void FreeTypeFont::RenderInteger(int number, float x, float y, float z, float sx, float sy)
    {
      std::ostringstream os;
      os &lt;&lt; number;
      std::string integer = os.str();
      RenderText(integer, x, y, z, sx, sy);
    }
  
    void FreeTypeFont::RenderCurrency(float amount, float x, float y, float z, float sx, float sy)
    {
      float rounded_amount = round(100.0f*amount)/100.0f;
      std::ostringstream os;
      os &lt;&lt; '$' &lt;&lt; amount;
      std::string money = os.str();
      /*
      while((money.substr(money.find('.'))).length() &gt; 3){
        money = money.substr(0, money.length()-1);
      }
      */
      RenderText(money, x, y, z, sx, sy);
    }
  
    float FreeTypeFont::CalcWidth(std::string str, float sx)
    {
      const char * text = str.c_str();
      float width = 0.0;
      previous = 0;
      FT_Vector delta;
      for(const char *p = text; *p; p++)
      {
        // Retrieve kerning distance and move pen position
        if(use_kerning &amp;&amp; previous &amp;&amp; *p)
        {
          FT_Get_Kerning(face, previous, *p, 0, &amp;delta);
          width += (delta.x &gt;&gt; 6);
        }
        width += Glyphs[*p].ax * sx;
        previous = *p;
      }
      return width;
    }
  
    float FreeTypeFont::CalcAveHeight(std::string str, float sy)
    {
      const char * text = str.c_str();
      float height = 0.0;
      for(const char *p = text; *p; p++) height += Glyphs[*p].ay * sy;
      height /= float(str.length());
      return height;
    }
  }
  </code></pre>
  
  <p>The custom library, g4tk, is compiled statically using CMake:</p>
  
  <pre><code># This is the CMakeLists file for the PhotonDemo program.
  cmake_minimum_required(VERSION 2.8.9)
  if(COMMAND CMAKE_POLICY)
    cmake_policy(SET CMP0003 NEW)
  endif()
  
  project(g4tk)
  
  # OpenGL
  find_package(OpenGL REQUIRED)
  if(OPENGL_FOUND)
    include_directories(${OPENGL_INCLUDE_DIRS})
    link_libraries(${OPENGL_LIBRARIES})
  endif()
  
  # GLEW
  find_package(GLEW REQUIRED)
  if(GLEW_FOUND)
    include_directories(${GLEW_INCLUDE_DIRS})
    link_libraries(${GLEW_LIBRARIES})
  endif()
  
  # GLFW
  find_package(PkgConfig REQUIRED)
  pkg_search_module(GLFW REQUIRED glfw3)
  include_directories(${GLFW_INCLUDE_DIRS})
  
  # FreeType
  find_package(Freetype REQUIRED)
  include_directories(${FREETYPE_INCLUDE_DIRS})
  
  # Add sources and headers
  set(SOURCE
    ${SOURCE}
    ${CMAKE_CURRENT_SOURCE_DIR}/OGLT.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/FreeTypeFont.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/LayerUI.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/UiTabs.cpp
  )
  
  set(HEADERS
    ${HEADERS}
    ${CMAKE_CURRENT_SOURCE_DIR}/OGLT.hpp
    ${CMAKE_CURRENT_SOURCE_DIR}/FreeTypeFont.hpp
    ${CMAKE_CURRENT_SOURCE_DIR}/LayerUI.hpp
    ${CMAKE_CURRENT_SOURCE_DIR}/UiTabs.hpp
  )
  
  add_library(g4tk STATIC ${SOURCE} ${HEADERS})
  </code></pre>
  
  <p>The library compiles fine, and I can use my library on the command line for a test program, for example:</p>
  
  <pre><code>g++ -g test.cpp -L/home/steven/C++/G4TK/Build -I/home/steven/C++/G4TK/Source -I/usr/include/freetype2 -lg4tk -lGLEW -lglfw3 -lGL -lX11 -lXi -lXrandr -lXxf86vm -lXinerama -lXcursor -lrt -lm -pthread -lfreetype
  </code></pre>
  
  <p>However, when I try to use my library in CMake to build another project, my library doesn't link with FreeType. Here's the CMakeLists.txt for the new sample project:</p>
  
  <pre><code># This is the CMakeLists file for the DIVS program.
  cmake_minimum_required(VERSION 2.8.9)
  if(COMMAND CMAKE_POLICY)
    cmake_policy(SET CMP0003 NEW)
  endif()
  
  project(DIVS)
  
  # Find ITK.
  find_package(ITK REQUIRED)
  include(${ITK_USE_FILE})
  
  # OpenGL
  find_package(OpenGL REQUIRED)
  if(OPENGL_FOUND)
    include_directories(${OPENGL_INCLUDE_DIRS})
    link_libraries(${OPENGL_LIBRARIES})
  endif()
  
  # GLEW
  find_package(GLEW REQUIRED)
  if(GLEW_FOUND)
    include_directories(${GLEW_INCLUDE_DIRS})
    link_libraries(${GLEW_LIBRARIES})
  endif()
  
  # GLFW
  find_package(PkgConfig REQUIRED)
  pkg_search_module(GLFW REQUIRED glfw3)
  include_directories(${GLFW_INCLUDE_DIRS})
  
  # FreeType
  find_package(Freetype REQUIRED)
  include_directories(${FREETYPE_INCLUDE_DIRS})
  
  include_directories(/home/steven/C++/G4TK/Source/)
  link_directories(/home/steven/C++/G4TK/Build/)
  
  # Set compiler flags and linked libraries
  SET(GCC_COVERAGE_COMPILE_FLAGS "-g")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
  
  # Add sources and headers
  set(SOURCE
    ${SOURCE}
    ${CMAKE_CURRENT_SOURCE_DIR}/Main.cpp
    #/home/steven/C++/G4TK/Source/FreeTypeFont.cpp
  )
  
  #set(HEADERS
  #  ${HEADERS}
  #)
  
  #add_executable(DIVS ${SOURCE} ${HEADERS})
  add_executable(DIVS ${SOURCE})
  
  target_link_libraries(DIVS ${ITK_LIBRARIES} ${GLEW_LIBRARIES} ${OPENGL_LIBRARIES} ${GLFW_STATIC_LIBRARIES} ${FREETYPE_LIBRARIES} -lg4tk)
  </code></pre>
  
  <p>And some sample errors:</p>
  
  <pre><code>FreeTypeFont.cpp:(.text+0x1c): undefined reference to 'FT_Init_FreeType'
  FreeTypeFont.cpp:(.text+0x62): undefined reference to 'FT_New_Face'
  FreeTypeFont.cpp:(.text+0xec): undefined reference to 'FT_Set_Pixel_Sizes'
  FreeTypeFont.cpp:(.text+0x142): undefined reference to 'FT_Load_Char'
  FreeTypeFont.cpp:(.text+0x273): undefined reference to 'FT_Load_Char'
  </code></pre>
  
  <p>So my FreeTypeFont class is not linking correctly. However, if I un-comment the "/home/steven/C++/G4TK/Source/FreeTypeFont.cpp" line the project compiles just fine. Is there a way for my library to compile without including the source code file in the CMakeLists.txt? I'm on Ubuntu 14.04 using GCC.</p>