Search code examples
c++cmakelinkerc++20

error using <filesystem> header with cmake and g++10


I am using #include<filesystem> c++ standered library in my cmake project with c++20 and g++10 on Ubuntu 20.4 LTS

// properties.hpp
#include <string>
#include <filesystem>
class File
{
private:
    std::filesystem::path m_filePath;
public:
    explicit File();
    ~File();
    void setPath(const std::string &p_fullPath);
};

// properties.cpp
#include "properties.hpp"

ff::prop::File::File() { this->setPath(""); }
ff::prop::File::~File() { this->setPath(""); }

void ff::prop::File::setPath(const std::string &p_fullPath)
{
    using namespace std::filesystem;
    if (p_fullPath == "")
        this->m_filePath = path();
    else
        this->m_filePath = path(p_fullPath);
}

My CMake configuration is as follows: -

cmake_minimum_required(VERSION 3.26 FATAL_ERROR)

### cmake settings
set(CXX_STANDARD_REQUIRED ON)
set(CXX_STANDARD 20)
set(CMAKE_CXX_COMPILER /usr/bin/g++-10)
cmake_language(GET_MESSAGE_LOG_LEVEL VERBOSE)
message("The c++ version is ${CXX_STANDARD} ${CMAKE_CXX_COMPILER}")

set(CMAKE_CXX_FLAGS_DEBUG_INIT "-Wall -Wextra -std=c++20")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wall")

### project setttings
project(ff  VERSION 0.0.1  LANGUAGES CXX)

add_executable(${PROJECT_NAME} 
  app/main.cpp
  app/src/app.cpp
  app/src/properties.cpp
)

When i run cmake -DCMAKE_BUILD_TYPE=Debug -S . -B debug I get the following output confirming hat the compiler version is running c++20: -

The c++ version is 20 /usr/bin/g++-10
-- Build spdlog: 1.11.0
-- Build type: Debug
-- Configuring done (0.3s)
-- Generating done (0.1s)
-- Build files have been written to: /home/projects/ff/debug

but when i run cmake --build debug/ i get the following linker errors: -

[ 50%] Building CXX object CMakeFiles/ff.dir/app/main.cpp.o
In file included from /home/projects/ff/app/headers/events/import.hpp:9,
                 from /home/projects/ff/app/headers/windows/file_win.hpp:12,
                 from /home/projects/ff/app/headers/windows/app_win.hpp:12,
                 from /home/projects/ff/app/headers/app.hpp:6,
                 from /home/projects/ff/app/main.cpp:1:
/home/projects/ff/app/headers/properties.hpp:27:18: error: ‘filesystem’ in namespace ‘std’ does not name a type
   27 |             std::filesystem::path m_filePath;
      |                  ^~~~~~~~~~
make[2]: *** [CMakeFiles/frameflow.dir/build.make:76: CMakeFiles/frameflow.dir/app/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:457: CMakeFiles/frameflow.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

I have tried Using #include<experimental/filesystem> with the same configuration while changing the std::filesystem::path to std::experimental::filesystem::path which results in a compilation but gives linker errs as it is not able to find the source of experimental filestrem.

My questions are,

  1. considering c++20 on g++10 has support for filesystem header then why does it not compile
  2. why does it compile with experimental/filesystem
  3. what do i do?

without came taking a minimal example

// a.hpp
#pragma once
#include <string>
#include <filesystem>

namespace ff::prop
{
    class File
    {
    private:
        std::filesystem::path m_filePath;
    public:
        explicit File();
        ~File();
        void setPath(const std::string &p_fullPath);
    };
} // namespace ff::prop
// a.cpp
#include "a.hpp"

ff::prop::File::File() { this->setPath(""); }
ff::prop::File::~File() { this->setPath(""); }

void ff::prop::File::setPath(const std::string &p_fullPath)
{
    using namespace std::filesystem;
    if (p_fullPath == "")
        this->m_filePath = path();
    else
        this->m_filePath = path(p_fullPath);
}
// main.cpp
#include "a.hpp"

int main() {
    ff::prop::File f();
    return EXIT_SUCCESS;
}

This when compiled with g++-10 main.cpp a.cpp -o app -std=20does compile.

To clarify : - after running cmake --system-information info.txt i get the following CMAKE_CXX_COMPILER == "/usr/bin/c++" but the compiler version uses 10.3.0 in both cases.


Solution

  • okay the problem might be something pretty dumb. You did this:

    set(CXX_STANDARD_REQUIRED ON)
    set(CXX_STANDARD 20)
    

    But those are not the variables you're looking for. It's CMAKE_CXX_STANDARD and CMAKE_CXX_STANDARD_REQUIRED.

    CXX_STANDARD and CXX_STANDARD_REQUIRED are target property names. If you want to use those, you should use set_property or set_target_properties. But at that point I'd suggest to look into target_compile_features.

    Next time, I'd suggest that you generate and inspect compile_commands.json to see what the compile command is actually being generated to. See also CMAKE_EXPORT_COMPILE_COMMANDS.

    Also, to future readers, make sure you set CMAKE_CXX_STANDARD before your add_library or add_executable. It's used as the default when the target is created.