Choc13
Choc13

Reputation: 796

C++ compiles with clang from command line, but not using CMake

I am trying to compile a simple test project to make sure all my tools, such as CMake, Boost, Clang are working.

The source code I am trying to compile is LibLinkTest.cpp:

#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <assert.h>

using namespace boost::filesystem;

int main(int argc, char* argv[])
{
    std::string str{"test passed"};
    std::cout << str << std::endl;
    boost::filesystem::path p{argv[1]};

    try {
        std::cout << p.string() << std::endl;
        if (exists(p)) {
            if (is_regular_file(p)) {
                std::ifstream file{p.c_str()};
                std::string line;
                if (file.good() && file.is_open()) {
                    while (file >> line) {
                        std::cout << line << std::endl;
                    }
                }
                file.close();
          } else if (is_directory(p)) {
              std::cout << p.string() << " is a directory " << std::endl;                                                 // path stream inserter
          } else
              std::cout << p.string() << " exists, but is neither a regular file nor a directory" << std::endl;
        }
        else {
            std::cout << p.string() << " does not exist" << std::endl;
        }
      }
    catch (const filesystem_error& ex) {
        std::cout << ex.what() << std::endl;
    }
}

Running:

c++ -std=c++11 -I /usr/boost_1_54_0/boost/ LibLinkTest.cpp -o LibTest -L /usr/boost_1_54_0/lib/ -lboost_filesystem -lboost_system

compiles it just fine and the code runs (with a seg fault, but I'll address that separately).

However, I want to use CMake with my other projects. Trying to compile LibLinkTest.cpp with the following CMakeLists.txt causes linking errors.

CMAKE_MINIMUM_REQUIRED (VERSION 2.6)

PROJECT(BoostTest CXX)

SET(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")

FIND_PACKAGE(Boost 1.54.0 COMPONENTS filesystem system REQUIRED)

INCLUDE_DIRECTORIES( 
    ${Boost_INCLUDE_DIR}
    /usr/include/
    /usr/include/c++/4.2.1/
)

ADD_EXECUTABLE(
    LibTest 
    LibLinkTest.cpp
)

TARGET_LINK_LIBRARIES(LibTest boost_filesystem boost_system)

The output from running cmake ../ is:

-- The CXX compiler identification is Clang 5.0.0
-- 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
-- Boost version: 1.54.0
-- Found the following Boost libraries:
--   filesystem
--   system
-- Configuring done
-- Generating done

And finally running make gives the error:

Scanning dependencies of target LibTest
[100%] Building CXX object CMakeFiles/LibTest.dir/LibLinkTest.cpp.o
Linking CXX executable LibTest
Undefined symbols for architecture x86_64:
  "std::string::c_str() const", referenced from:
      boost::system::system_error::what() const in LibLinkTest.cpp.o
      boost::filesystem::path::c_str() const in LibLinkTest.cpp.o
  "std::string::empty() const", referenced from:
      boost::system::system_error::what() const in LibLinkTest.cpp.o
  "std::basic_ios<char, std::char_traits<char> >::good() const", referenced from:
      _main in LibLinkTest.cpp.o

It seems like a setting in CMake is not correct, perhaps something that points to the std c++ lib. Does anyone know how I can configure CMake correctly?

Upvotes: 4

Views: 2697

Answers (3)

Choc13
Choc13

Reputation: 796

I have solved this by changing the line:

SET(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")

to

SET(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libstdc++")

It seems like I had just made a typo in the CMakeLists.txt.

On a side note, does anyone know why I need to set this flag? Is it a C++11 thing? It also seems to have solved my issues with the seg fault that I was getting when compiling from the command line.

Upvotes: 3

David Brown
David Brown

Reputation: 13536

You should change the line

TARGET_LINK_LIBRARIES(LibTest boost_filesystem boost_system)

to

TARGET_LINK_LIBRARIES(LibTest ${Boost_LIBRARIES})

The FIND_PACKAGE command sets the Boost_LIBRARIES variable to what you need to link with.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409472

If you see these two lines from the output

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

It tells you that it might not be clang that is used to compile the source. To see if it is, to e.g.

$ c++ --version

to see what compiler it actually is. If it doesn't say clearly you may want to do e.g.

$ ls -l /usr/bin/c++

and if it's a symbolic link then check the link (and so on). On my system (Ubuntu 13.10) the file /usr/bin/c++ is a symbolic link to /etc/alternatives/c++ which is a symbolic link to /usr/bin/g++, meaning that on my system the command c++ is actually the GCC C++ compiler.

To make sure you use clang, then redo the cmake command (from a clean folder, that you haven't run cmake in before) with the environment variable CXX set to clang++, like

$ CXX=clang++ cmake path/to/folder/with/CMakeLists.txt

Pro-tip: Make a separate folder for building, and run cmake from it. Then you can easily clean it up by just removing it if needed.

Upvotes: 0

Related Questions