PT is a template for modern C++ projects with useful features for developing cross-platform products.
A template for modern C++ projects with useful features for developing cross-platform projects.
This repository is a modern project template based on C++ and CMake build tool.
cd build
cmake ..
make
./ProjectTemplate
How to sync project from template source?
cmake .. -DPROJECT_NAME="Your Project Name" -DPROJECT_CREATOR="Kambiz" -DPROJECT_VERSION_TYPE="beta" -DPROJECT_DESCRIPTION="This is my awesome project" -DPROJECT_LICENSE_TYPE="mit"
Change PROJECT_NAME variable to your own project name.
Change PROJECT_CREATOR variable to your main project developer.
Change PROJECT_DESCRIPTION variable to your project description.
Change PROJECT_HOMEPAGE_URL variable to your project official url.
Change PROJECT_VERSION_TYPE variable to your project version based on semantic versioning.
The project output structure is based on "application" with gui by default, so if you want to change it, you should change the PROJECT_USAGE_TYPE and PROJECT_MAIN_TYPE variables.
Change the DEVELOPER_BUNDLE_IDENTIFIER variable for your own developer id, especially in Apple products, you should set it according to the bundle string in Xcode.
The language standard is based on C++17 by default, you can change it via CMAKE_CXX_STANDARD variable.
Finally, specify software version for the variables PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH and PROJECT_VERSION_TWEAK.
Enjoy your project! :)
These features can be useful in downloading, building, and integrating prerequisites into your project.
So you can set cmake option variable for enabling them.
Include latest standard of C++
cmake .. -DUSE_LATEST_STANDARD=true
cmake .. -DUSE_BOOST=true
cmake .. -DGUI_APPLICATION=true
cmake .. -DFORCE_UPGRADED_LIBS=false
cmake .. -DHAS_USER_INTERFACE=true
cmake .. -DPROJECT_MAIN_TYPE=stl
cmake .. -DPROJECT_USAGE_TYPE=application
cmake .. -DDEVELOPER_BUNDLE_IDENTIFIER=com.kambizasadzadeh.app
cmake .. -DUSE_QT_QUICK_COMPILER=false
cmake .. -DUSE_CURL=true
cmake .. -DUSE_FMT=true
cmake .. -DUSE_CPP_CHECK=true
cmake .. -DUSE_GOOGLE_TEST=true
cmake .. -DUSE_DOC_TEST=true
cmake .. -DUSE_CATCH2=true
cmake .. -DUSE_CTRE=true
cmake .. -DUSE_JSON=true
cmake .. -DUSE_OPENSSL=true
cmake .. -DDUSE_ZLIB=true
cmake .. -DENABLE_CLANG_TIDY=true
cmake .. -DSIMPLE_BUILD=true
cmake .. -DENABLE_ASAN=true
cmake .. -DENABLE_WARN_MODE=true
cmake .. -DENABLE_SAFE_ONLY=true
cmake .. -DBUILD_DEBUG_MODE=true
cmake .. -DDEBUG_LOGGING=true
cmake .. -DENABLE_STATIC_LIB_BUILD=true
cmake .. -DENABLE_DEVELOPER_MODE=true
cmake .. -DENABLE_TODO_MODE=true
cmake .. -DENABLE_EXPERIMENTAL_MODE=true
cmake .. -ENABLE_SHARED_LIB_BUILD=true
cmake .. -FORCE_LATEST_STANDARD_FEATURE=true
cmake .. -DOPTIMIZATION_LEVEL=0
You can set or change your project's basic information such as name, description, link, etc.
set(PROJECT_NAME "ProjectTemplate" CACHE STRING "Project Name")
set(PROJECT_TARGET ${PROJECT_NAME} CACHE STRING "Target Name")
set(PROJECT_CREATOR "Kambiz Asadzadeh")
project(
${PROJECT_NAME}
LANGUAGES CXX
DESCRIPTION "Description of your project."
HOMEPAGE_URL "https://kambizasadzadeh.com"
VERSION ${PROJECT_VERSION}
)
-- The CXX compiler identification is AppleClang 12.0.0.12000032
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Ready for Apple Silicon.
-- Performing Test COMPILER_SUPPORTS_CXX23
-- Performing Test COMPILER_SUPPORTS_CXX23 - Success
-- Performing Test COMPILER_SUPPORTS_CXX20
-- Performing Test COMPILER_SUPPORTS_CXX20 - Success
-- Performing Test COMPILER_SUPPORTS_CXX17
-- Performing Test COMPILER_SUPPORTS_CXX17 - Success
-- Performing Test COMPILER_SUPPORTS_CXX14
-- Performing Test COMPILER_SUPPORTS_CXX14 - Success
-- Performing Test COMPILER_SUPPORTS_CXX11
-- Performing Test COMPILER_SUPPORTS_CXX11 - Success
-- Performing Test COMPILER_SUPPORTS_CXX0X
-- Performing Test COMPILER_SUPPORTS_CXX0X - Success
-- ------ ProjectTemplate Tools Configuration ------
-- Language Standard : C++[20]
-- Compiler : AppleClang
-- Compiler Version : 12.0.0.12000032
-- OS Target : Darwin-20.3.0
-- OS Version :
-- System Architecture : x86_64
-- Project License : MIT
-- ------ ProjectTemplate Framework Info ------
-- Name : ProjectTemplate
-- Description : Description of your project.
-- Version :
-- ------ ProjectTemplate Project Configuration ------
-- DEVELOPER :
-- PROJECT_PROJECT :
-- PROJECT_TARGET : ProjectTemplate
-- PROJECT_VERSION : 1.0.2.0
-- PROJECT_VERSION_TYPE : final
-- ------ ProjectTemplate Building Configuration ------
-- PROJECT_BUILD_SHARED :
-- PROJECT_VERSION_TAG_HEX : 0x00000000
-- PROJECT_FOLDER_SUFFIX :
-- LIBRARY_OUTPUT_PATH : .../Project-Template/build/lib
-- CMAKE_CURRENT_SOURCE_DIR : .../Project-Template
-- ------ ProjectTemplate End Configuration ------
-- Configuring done
#if defined(HAS_USER_INTERFACE) && defined(USE_QT)
//! Qt
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
#else
#include <iostream>
#include "utilities/featuretest.hpp"
//! Examples
#include "examples/compilertest.hpp"
#include "examples/platformtest.hpp"
#include "examples/librarytest.hpp"
#include "examples/languagetest.hpp"
#include "examples/configtest.hpp"
//!JSon [Non-STL] Features
#include <nlohmann/json.hpp>
//!Google Test
#ifdef USE_GOOGLE_TEST
#include <gtest/gtest.h>
class Counter {
public:
// Returns the current counter value, and increments it.
int Increment() {
return m_counter++;
}
// Returns the current counter value, and decrements it.
// counter can not be less than 0, return 0 in this case
int Decrement() {
if (m_counter == 0) {
return m_counter;
} else {
return m_counter--;
}
}
// Prints the current counter value to STDOUT.
void Print() const {
printf("%d", m_counter);
}
private:
int m_counter;
};
//TEST UNIT
TEST(Counter, Increment) {
Counter c;
// Test that counter 0 returns 0
EXPECT_EQ(0, c.Decrement());
// EXPECT_EQ() evaluates its arguments exactly once, so they
// can have side effects.
EXPECT_EQ(0, c.Increment());
EXPECT_EQ(1, c.Increment());
EXPECT_EQ(2, c.Increment());
EXPECT_EQ(3, c.Decrement());
}
#endif
//!Catch2
#ifdef USE_CATCH2
# include <catch2/catch_all.hpp>
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
unsigned int Factorial( unsigned int number ) {
return number <= 1 ? number : Factorial(number-1)*number;
}
TEST_CASE( "Factorials are computed", "[factorial]" ) {
REQUIRE( Factorial(1) == 1 );
REQUIRE( Factorial(2) == 2 );
REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(10) == 3628800 );
}
#endif
using namespace std;
int main()
{
cout << "Hello World!" << endl;
//!Config Test
ConfigTest config;
config.readSettings();
//!Compiler Test
CompilerTest compiler;
compiler.getCompilerInfo();
//!Platform Test
PlatformTest platform;
platform.getPlatformInfo();
//!Library Test
LibraryTest library;
library.testBoost(); // Boost
//!Language Features
LanguageTest language;
language.checkFeatures();
//!ThirdParty Library
ThirdPartyTest thirdPartyTest;
thirdPartyTest.testFmt();
return 0;
}
#endif
cout << "Compiler Name : " << __COMPILER__ << endl;
cout << "Compiler Version : " << __COMPILER_VER__ << endl;
#if defined(__COMPILER_CLANG_LLVM_)
cout << "Clang compiler has been detected!\n";
#elif defined(__COMPILER_INTEL__)
cout << "Intel compiler has been detected!\n";
#elif defined(__COMPILER_MINGW__)
cout << "MinGW compiler has been detected!\n";
#elif defined(__COMPILER_MINGW_64__)
cout << "MinGW64 compiler has been detected!\n";
#elif defined(__COMPILER_GCC__)
cout << "GCC compiler has been detected!\n";
#elif defined(__COMPILER__HEWLETT_)
cout << "Hewlett compiler has been detected!\n";
#elif defined(__COMPILER_IBM__)
cout << "IBM compiler has been detected!\n";
#elif defined(__COMPILER_MSVC__)
cout << "MSVC compiler has been detected!\n";
#elif defined(__COMPILER_PGCC__)
cout << "PGCC compiler has been detected!\n";
#elif defined(__COMPILER_ORACLE__)
cout << "Oracle compiler has been detected!\n";
#endif
#if defined(PLATFORM_MAC)
cout << "This is macOS platform!\n";
#elif defined(PLATFORM_WINDOWS)
cout << "This is Windows platform!\n";
#elif defined(PLATFORM_LINUX)
cout << "This is Linux platform!\n";
#elif defined(PLATFORM_FREEBSD)
cout << "This is freeBSD platform!\n";
#elif defined(PLATFORM_OPENBSD)
cout << "This is openBSD platform!\n";
#elif defined(PLATFORM_VXWORKS)
cout << "This is VXWorks platform!\n";
#elif defined(PLATFORM_MOTOROLA)
cout << "This is Motorola platform!\n";
#elif defined(PLATFORM_ULTRIX)
cout << "This is Ultrix platform!\n";
#elif defined(PLATFORM_DOS)
cout << "This is Dos platform!\n";
#elif defined(PLATFORM_WINDOWS_PHONE)
cout << "This is Windows Phone platform!\n";
#elif defined(PLATFORM_IOS_SIMULATOR)
cout << "This is iOS Simulator platform!\n";
#elif defined(PLATFORM_IOS)
cout << "This is iOS platform!\n";
#elif defined(PLATFORM_APPLE_TV)
cout << "This is AppleTV platform!\n";
#elif defined(PLATFORM_IWATCH)
cout << "This is iWatch platform!\n";
#elif defined(PLATFORM_ANDROID)
cout << "This is Android platform!\n";
#endif
#include "include/common.hpp"
#include <iostream>
#ifdef USE_BOOST
#include <boost/chrono.hpp>
#endif
LibraryTest::LibraryTest()
{
}
void LibraryTest::testBoost() const noexcept
{
//!Boost Library
#ifdef USE_BOOST
std::cout << "Boost version " << BOOST_VERSION << std::endl;
std::cout << "Boost Lib Clock Test\n";
boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
for ( long i = 0; i < 10000000; ++i )
std::sqrt( 123.456L ); // burn some time
boost::chrono::duration<double> sec = boost::chrono::system_clock::now() - start;
std::cout << "took " << sec.count() << " seconds\n";
#else
std::cout << "Boost Library is not available.\n";
#endif
}
#ifdef USE_FEATURE_TEST
if (print.general_features) show("C++ GENERAL", cxx);
if (print.cxx11 && print.core_features) show("C++11 CORE", cxx11);
if (print.cxx14 && print.core_features) show("C++14 CORE", cxx14);
if (print.cxx14 && print.lib_features ) show("C++14 LIB" , cxx14lib);
if (print.cxx17 && print.core_features) show("C++17 CORE", cxx17);
if (print.cxx17 && print.lib_features ) show("C++17 LIB" , cxx17lib);
if (print.cxx20 && print.core_features) show("C++20 CORE", cxx20);
if (print.cxx20 && print.lib_features ) show("C++20 LIB" , cxx20lib);
if (print.cxx23 && print.core_features) show("C++23 CORE", cxx23);
if (print.cxx23 && print.lib_features ) show("C++23 LIB" , cxx23lib);
if (print.attributes) show("ATTRIBUTES", attributes);
#else
std::cout << "Test Feature is not available.\n";
#endif
#include "config.hpp"
#include <iostream>
std::cout << "========CONFIG TEST========" << std::endl;
std::cout << "Project Name : " << PROJECT_NAME << std::endl;
std::cout << "Project Description : " << PROJECT_DESCRIPTION << std::endl;
std::cout << "Project Homepage Url : " << PROJECT_HOMEPAGE_URL << std::endl;
std::cout << "Project Language : " << PROJECT_LANGUAGES << std::endl;
std::cout << "Project Full Version : " << PROJECT_VERSION_STRING << std::endl;
std::cout << "Project Creator : " << PROJECT_CREATOR << std::endl;
std::cout << "Project License Type : " << PROJECT_LICENSE_TYPE << std::endl;
std::cout << "========CONFIG TEST========" << std::endl;