Hur bygger jag ett CMake projekt från ett MSBuild projekt?

Permalänk

Hur bygger jag ett CMake projekt från ett MSBuild projekt?

Hur bygger jag ett CMake projekt från ett MSBuild projekt?
Jag ska kompilera C++ kod i Linux och jag behöver något som kan kompilera mitt projekt.

Permalänk
Hedersmedlem

Är det ett komplicerat bygge, eller kommer man undan med ”kompilera alla filer i mappen”?
Det är nog inte helt enkelt att konvertera till cmake (gissar jag, msbuild är ju inte heller tillgängligt i linux), men det är kanske möjligt att skapa ett nytt projekt?

Edit:
Jag har inte testat, men denna kanske gör något bra:
https://github.com/pavelliavonau/cmakeconverter

Permalänk

Tackar.

Jag håller på virtualisera linux så jag kan testa skapa en CMake med cmake-converter.
Det tar ett tag.

Permalänk

cmake-converter fungerar....men när jag ska bygga mitt program med vcpkg, så säger den att den saknar bibliotek. Alltså inte vcpkg, utan cmake kan inte hitta biblioteken.

Finns det inget bättre alternativ än cmake?

Permalänk
Hedersmedlem
Skrivet av heretic16:

cmake-converter fungerar....men när jag ska bygga mitt program med vcpkg, så säger den att den saknar bibliotek. Alltså inte vcpkg, utan cmake kan inte hitta biblioteken.

Finns det inget bättre alternativ än cmake?

Har du sett denna?
https://learn.microsoft.com/en-us/vcpkg/users/buildsystems/cm...

Permalänk

Jag har försökt med detta, precis denna länk.
Men jag har inte kommit vidare.

Däremot har jag hittat en lösning: https://www.youtube.com/watch?v=af-1hDfoRcg&ab_channel=AllAbo...

Att kompilera kod, som skickas till linuxmaskiner över SSH. Det fungerar fint.
Men nu är nästa problem. Jag måste ha underbibliotek.

Jag vet inte hur man får denna Linux Embedded GDB att fungera med vcpkg.
Är det så här man inkluderar bibliotek?

Nu har det börjat bli bättre.
Jag hittade en lösning https://www.youtube.com/watch?v=j13iYc6zRuk&ab_channel=BoostM...

Men varför är det felmeddelanden fortfarande kvar? Jag använder mig av C++20.

Jag ändrade till C++2a och då försvann alla dessa tusen felmeddelanden. Men istället så kan den inte läsa dom där biblioteken som jag inkluderade. Notera att det är skumt att min IDE kan hitta filerna, men inte min kompilator.

Permalänk
Datavetare
Skrivet av heretic16:

cmake-converter fungerar....men när jag ska bygga mitt program med vcpkg, så säger den att den saknar bibliotek. Alltså inte vcpkg, utan cmake kan inte hitta biblioteken.

Finns det inget bättre alternativ än cmake?

Vcpkg och cmake verkar ju vara en combo som explicit stöds. Läste du denna del ("Using vcpkg with CMake")?

Här är en rätt minimalistiskt CMakeLists.txt som fungerar ihop med vcpkg

cmake_minimum_required(VERSION 3.12) project(foo) # Should really be passed to cmake via the switch # -DCMAKE_TOOLCHAIN_FILE="<VCPKG_INSTALL_DIR>/scripts/buildsystems/vcpkg.cmake" set(CMAKE_TOOLCHAIN_FILE d:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "vcpkg toolchain file") set(CMAKE_CXX_STANDARD 17) file(GLOB foo_SRC CONFIGURE_DEPENDS "*.h" "*.cpp") add_executable(foo_bin ${foo_SRC}) # Locate headers and library for SQLite find_package(unofficial-sqlite3 CONFIG REQUIRED) target_link_libraries(foo_bin PRIVATE unofficial::sqlite3::sqlite3)

Går då att t.ex. göra detta

#include <iostream> #include <sqlite3.h> int main(int argc, const char *argv[]) { std::cout << "SQLite3 version " << sqlite3_libversion() << std::endl; }

På Windows är standardvalet för cmake att skapa en Visual Studio solution, på Linux kommer det bli en gmake fil.

Vad man behöver stoppa in för att länka med ett bibliotek skriver vcpkg ut vid installation av biblioteket, tar man SQLite3 t.ex.

vcpkg install sqlite3:x64-windows Computing installation plan... The following packages are already installed: sqlite3[core]:x64-windows -> 3.40.1#1 sqlite3:x64-windows is already installed Restored 0 package(s) from C:\Users\kenne\AppData\Local\vcpkg\archives in 77 us. Use --debug to see more details. Total install time: 267.7 us sqlite3 provides pkgconfig bindings. sqlite3 provides CMake targets: find_package(unofficial-sqlite3 CONFIG REQUIRED) target_link_libraries(main PRIVATE unofficial::sqlite3::sqlite3)

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk

Jag har testat installerat Eclipse CDT och försökt få in mitt projekt där. Men Eclipse CDT klagar på allt. Den klagar till och med på vector.

Jag har använt mig av MSVC kompilatorn, och den kanske skiljer sig från vanlig GCC?
Jag menar, MSVC accepterar att man blandar C och C++ kod, medan GCC gillar inte det.

Jag använde t.ex. strcpy_s som är en minnessäker funktion, men GCC gillade inte den för strcpy_s är en C funktion, inte C++.

Jag försöker få ImGui för Linux.

Jag har testat lite saker. Första är att kompilera med GCC på linux. Det fungerar halvt, för att kompilatorn klagar väldigt mycket på C++ koden. Sedan har Eclipse något konstigt beteende som gör så att den säger att "Funktionen finns inte", men ändå finns den. Eller att den klagar på "Felaktiga argument", än fast argumenten är korrekta.

Sedan har jag testat att kompilera C++ kod på Windows med ett speciellt plugin för Visual Studio Community 2022. Då kan jag alltså skriva C++ kod för linux, på windows som sedan överförs till Linux via SSH. Detta fungerar bra! Problemet är att jag måste ha linux-bibliotek i vcpkg och vcpkg tillåter inte mig att installera linuxbibliotek hos windows.

Så där blir det ett problem. Men jag jobbar vidare på Vcpkg. Det måste fungera att få ned linuxbibliotek för windows.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Jag menar, MSVC accepterar att man blandar C och C++ kod, medan GCC gillar inte det.

Jag använde t.ex. strcpy_s som är en minnessäker funktion, men GCC gillade inte den för strcpy_s är en C funktion, inte C++.

Nja, det där borde fungera. Exakt vad klagar den på?

Permalänk
Skrivet av Elgot:

Nja, det där borde fungera. Exakt vad klagar den på?

Den klagar på std::map, strcpy_s, std::memset, sprintf_s osv. Detta inträffar i Eclipse.

Jag har en liten teori! Med tanke på att jag ska kompilera för Linux. Alla linux-distar har ett eget paketeringssystem. Dom enda bibliotek som jag behöver är Boost Asio, Libmodbus, OpenGL, Boost Filesystem, Boost Date Time och MySQL C++ Connector.

Allt detta finns ju redan färdiga som paket i t.ex. Ubuntu.

Så det skulle bara fungera för mig att installera dessa bibliotek och sedan kompilera min main.cpp fil som vanligt.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Den klagar på std::map, strcpy_s, std::memset, sprintf_s osv. Detta inträffar i Eclipse.

Vad säger den? Är det kompilatorn som inte hittar saker, eller bara eclipse?

Skrivet av heretic16:

Jag har en liten teori! Med tanke på att jag ska kompilera för Linux. Alla linux-distar har ett eget paketeringssystem. Dom enda bibliotek som jag behöver är Boost Asio, Libmodbus, OpenGL, Boost Filesystem, Boost Date Time och MySQL C++ Connector.

Allt detta finns ju redan färdiga som paket i t.ex. Ubuntu.

Så det skulle bara fungera för mig att installera dessa bibliotek och sedan kompilera min main.cpp fil som vanligt.

Ja, det är ju den traditionella metoden. Vcpkg (och liknade) är rätt nya påhitt (och de har ju inte alla bibliotek heller).

Permalänk
Skrivet av Elgot:

Vad säger den? Är det kompilatorn som inte hittar saker, eller bara eclipse?

Ja, det är ju den traditionella metoden. Vcpkg (och liknade) är rätt nya påhitt (och de har ju inte alla bibliotek heller).

Den säger "cannot be resolved". Detta är en klassiker. Ofta handlar det om att man har glömt att importera en .h fil. Men jag har verkligen varit noga på detta att .h filerna ska var på rätt plats och dom ska länkas i programmet.

Jag ska försöka med den traditionella metoden. Det är ju bara för Linux jag ska hålla på så där med.

Nu när jag kör på den traditionella metoden, så blev det enklare att skapa min CMakeLists.txt

cmake_minimum_required(VERSION 3.18) project(ProgramNamn) file(GLOB_RECURSE SOURCES "src/*.cpp") file(GLOB_RECURSE INCLUDES "src/*.h") include_directories(${INCLUDES}) add_executable(ProgramNamn ${SOURCES})

Jag har anropat

cmake -B build .

Och nu fick jag en mapp som heter build.
Jag bygger nu mitt program

cmake --build build

Och nu klagar den på att strcpy_s was not decleared.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Och nu klagar den på att strcpy_s was not decleared.

Och du har inkluderat string.h ?

Permalänk
Skrivet av Elgot:

Och du har inkluderat string.h ?

Japp!

Även lagt till

set(CMAKE_C_COMPILER "/usr/bin/clang") set(CMAKE_CXX_COMPILER "/usr/bin/clang++") set(CMAKE_CXX_STANDARD 20) set(CMAKE_BUILD_TYPE "Release") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")

Permalänk
Hedersmedlem
Skrivet av heretic16:

Fungerar det att lägga till
#define __STDC_WANT_LIB_EXT1__ 1
innan du inkluderar string.h?

Permalänk
Skrivet av Elgot:

Fungerar det att lägga till
#define __STDC_WANT_LIB_EXT1__ 1
innan du inkluderar string.h?

Nej. Det är inte bara jag som har problem med detta.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Nej. Det är inte bara jag som har problem med detta.

Jag vet inte hur många det är som faktiskt använder dessa…

Permalänk
Skrivet av Elgot:

Jag vet inte hur många det är som faktiskt använder dessa…

I detta fall ser min kod ut så här

char text[200]; strcpy_s(text, selectedItems.at(i).c_str());

Där selectedItems är alltså en std::vectror<std::string>. Så det handlar om att överföra en std:string till en char[] array.
Visst, jag kan lösa detta på ett annat sätt också. std::memcpy går ju, men det blir inte lika bra.

Permalänk
Hedersmedlem
Skrivet av heretic16:

I detta fall ser min kod ut så här

char text[200]; strcpy_s(text, selectedItems.at(i).c_str());

Jag tror att du måste skicka med buffertens storlek där också.

Skrivet av heretic16:

Visst, jag kan lösa detta på ett annat sätt också. std::memcpy går ju, men det blir inte lika bra.

strncpy är ju ett annat alternativ.

Permalänk
Skrivet av Elgot:

Jag tror att du måste skicka med buffertens storlek där också.
strncpy är ju ett annat alternativ.

Bufferten kommed med automatiskt. strcpy_s är en unik funktion som känner av arrayens storlek. Notera att det måste vara en array och inte pekar-array.

strncpy ger ett fel från min MSVC kompilator att den rekommenderar strncpy_s.

Så så fort det kommer till dessa funktioner. ctime_s, strcpy_s, strncpy_s osv, då fungerar dom inte.
Jag kan ju avvaktivera dessa varningar i min MSBuild....men detta känns som man gör fel då.
Alla dessa _s funktioner finns ju av en anledning att det ska vara minnessäkert.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Bufferten kommed med automatiskt. strcpy_s är en unik funktion som känner av arrayens storlek. Notera att det måste vara en array och inte pekar-array.

Det kan vara så att Microsoft har egna utökningar. Basfunktionen är strcpy_s(x, <maxlängd>, y) och den ökade säkerheten kommer ju främst av att man inte kan råka skriva över målet med obegränsad mängd data av misstag.

Permalänk
Skrivet av Elgot:

Det kan vara så att Microsoft har egna utökningar. Basfunktionen är strcpy_s(x, <maxlängd>, y) och den ökade säkerheten kommer ju främst av att man inte kan råka skriva över målet med obegränsad mängd data av misstag.

Jag avaktiverade felmeddelanden och kör endast på C++ funktioner.
Ja, det måste vara Microsofts egna hittepå det här.

Nu går jag vidare i min kompilering. Jag stöter på lite saker som jag löser Men en snabb fråga! Mysqlx, dvs MySQL Connector C++.

I Windows så importerar jag med #include <mysqlx/xdevapi.h>, Men i Linux (Ubuntu) finns inte denna!
Jag testar installera via

sudo apt install libmysqlcppconn-dev

Visst, jag får en mapp i /usr/include/cppconn, men jag vet inte vilka filer jag ska använda. Troligtvis har jag installerat fel bibliotek.

Permalänk

Nu har jag fått det att fungera! Nu är det inget som saknas.

Men den klagar nu på Mysql funktionerna. Jag tror jag har glömt att länka till .lib-arna. Eller måste man göra det också med CMake?

Den säger "undefined reference too...." och sedan funktionens namn. Men .h filen verkar den hitta.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Nu har jag fått det att fungera! Nu är det inget som saknas.

Men den klagar nu på Mysql funktionerna. Jag tror jag har glömt att länka till .lib-arna. Eller måste man göra det också med CMake?

Den säger "undefined reference too...." och sedan funktionens namn. Men .h filen verkar den hitta.

Trevligt!

Ja, man brukar typiskt specificera bibliotek med target_link_libraries

Permalänk

Ja. Jag har fått det fungera med kompileringen. Men gud vilket bök det var! Jag har aldrig varit med om något sådant testande fram och tillbaka.

Men det fungerar!

Permalänk
Hedersmedlem
Skrivet av heretic16:

Ja. Jag har fått det fungera med kompileringen. Men gud vilket bök det var! Jag har aldrig varit med om något sådant testande fram och tillbaka.

Men det fungerar!

Det tar lite tid att vänja sig, men det är nästan samma varje gång. Du kan troligen (med endast mindre justering) återanvända din konfiguration till nästa projekt.

Permalänk
Skrivet av Elgot:

Det tar lite tid att vänja sig, men det är nästan samma varje gång. Du kan troligen (med endast mindre justering) återanvända din konfiguration till nästa projekt.

Jag tyckte det var väldigt bra att man kan iterera igenom mapparna, istället för att skriva ut den absoluta sökvägen till varje fil. Det var ett smart sätt!

Dock så är min CMakeLists.txt anpassat för ubuntu/debian då vissa paket som jag installerar med sudo apt-get install, installerar sig i speciella mappar i /usr/include

Jag vet inte hur det ser ut för Fedora och Suse.

Något som jag blev förvånad över när jag kompilerade var att man fick mycket varningar, som ej påverkade något. Varför ens finns dom?

Permalänk
Hedersmedlem
Skrivet av heretic16:

Jag tyckte det var väldigt bra att man kan iterera igenom mapparna, istället för att skriva ut den absoluta sökvägen till varje fil. Det var ett smart sätt!

Dock så är min CMakeLists.txt anpassat för ubuntu/debian då vissa paket som jag installerar med sudo apt-get install, installerar sig i speciella mappar i /usr/include

Jag vet inte hur det ser ut för Fedora och Suse.

Det där fungerar nästan automatiskt om man använder find-funktionerna. För att använda Boost kan man till exempel köra:

find_package(Boost 1.56 REQUIRED COMPONENTS date_time filesystem iostreams) add_executable(foo foo.cc) target_link_libraries(foo Boost::date_time Boost::filesystem Boost::iostreams)

För att leta rätt på en boost-installation av rätt version och sedan länka till några av dess bibliotek. Det fungerar typiskt oavsett vilket operativsystem man kör och vilken kompilator man använder.

Skrivet av heretic16:

Något som jag blev förvånad över när jag kompilerade var att man fick mycket varningar, som ej påverkade något. Varför ens finns dom?

Av cmake eller gcc? Varningar är ju till för att uppmärksamma dig på saker som skulle kunna ge problem men inte är direkt otillåtna.

Permalänk
Skrivet av Elgot:

Det där fungerar nästan automatiskt om man använder find-funktionerna. För att använda Boost kan man till exempel köra:

find_package(Boost 1.56 REQUIRED COMPONENTS date_time filesystem iostreams) add_executable(foo foo.cc) target_link_libraries(foo Boost::date_time Boost::filesystem Boost::iostreams)

För att leta rätt på en boost-installation av rätt version och sedan länka till några av dess bibliotek. Det fungerar typiskt oavsett vilket operativsystem man kör och vilken kompilator man använder.

Så här ser min CMakeLists.txt ut.
Säg till om du ser förbättringar som kan göras.

cmake_minimum_required(VERSION 3.18) project(ProgramTest) set(CMAKE_CXX_STANDARD 20) set(CMAKE_BUILD_TYPE "Release") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") file(GLOB_RECURSE SOURCES "ProgramTest/*.cpp") file(GLOB_RECURSE INCLUDES "ProgramTest/*.h") add_executable(ProgramTest ${SOURCES}) include_directories(${INCLUDES}) # Hitta och länka mot libmodbus find_library(LIBMODBUS_LIBRARY NAMES modbus PATHS /usr/lib/x86_64-linux-gnu) if (LIBMODBUS_LIBRARY) target_link_libraries(ProgramTest PRIVATE ${LIBMODBUS_LIBRARY}) else() message(FATAL_ERROR "Libmodbus library not found") endif() # Hitta och länka mot MySQL C++ Connector find_library(LIBMYSQLCPPCONN_LIBRARY NAMES mysqlcppconn8 PATHS /usr/lib/x86_64-linux-gnu) if (LIBMYSQLCPPCONN_LIBRARY) target_link_libraries(ProgramTest PRIVATE ${LIBMYSQLCPPCONN_LIBRARY}) else() message(FATAL_ERROR "MySQL C++ Connector library not found") endif() # Hitta och länka mot boost-asio find_package(Boost REQUIRED COMPONENTS system) if (Boost_FOUND) target_link_libraries(ProgramTest PRIVATE Boost::system) else() message(FATAL_ERROR "Boost library not found") endif() # Hitta och länka mot boost-filesystem find_package(Boost REQUIRED COMPONENTS filesystem) if (Boost_FOUND) target_link_libraries(ProgramTest PRIVATE Boost::filesystem) else() message(FATAL_ERROR "Boost Filesystem library not found") endif() # Hitta och länka mot OpenGL find_package(OpenGL REQUIRED) if (OpenGL_FOUND) target_link_libraries(ProgramTest PRIVATE OpenGL::GL) else() message(FATAL_ERROR "OpenGL library not found") endif() # Hitta och länka mot GLFW3 find_package(glfw3 REQUIRED) if (glfw3_FOUND) target_link_libraries(ProgramTest PRIVATE glfw) else() message(FATAL_ERROR "GLFW3 library not found") endif()

Citat:

Av cmake eller gcc? Varningar är ju till för att uppmärksamma dig på saker som skulle kunna ge problem men inte är direkt otillåtna.

Det var varningar, som inte betydde något. Den kunde klagar på att en .h fil är ingen mapp. Jaha? Tänkte jag.
Så jag tog denna varning med nypa salt.

Jag tror det har med

file(GLOB_RECURSE SOURCES "ProgramTest/*.cpp") file(GLOB_RECURSE INCLUDES "ProgramTest/*.h")