Skip to content

Instantly share code, notes, and snippets.

@AntonioCS
Last active November 22, 2020 07:56
Show Gist options
  • Save AntonioCS/81e96d20bc8538db8a2e469f01294f6f to your computer and use it in GitHub Desktop.
Save AntonioCS/81e96d20bc8538db8a2e469f01294f6f to your computer and use it in GitHub Desktop.
Small bat file to create basic project. Will create src/ dir if not present (with dummy code). Will create tests/ folder if not present (with dummy test code). Will create build/ folder (if present with a .sln file ask if you want to delete). Check if there is a CMakeLists.txt and if there isn't create a generic one.
@echo off
@setlocal EnableExtensions EnableDelayedExpansion
:: This batch file will try to generate a minimalist project
:: It will create a src folder with a small cpp file^
:: It will create a test folder with some mock test files for catch2/catch
:: It will also ask if you want to enable testing
:: If a solution already exists (in the build folder) it will ask if you want to remove it and rebuild
:: NOTE: Run this in admin mode if it doesn't work
set cmake_batch_version=0.8
set rootDir=%~dp0%
set rootDir=%rootDir:\=/%
set srcDir=%rootDir%
set srcCodeDir=%rootDir%src
set testDir=%rootDir%tests
set builDir=%rootDir%build
set gitDir=%rootDir%.git
set toolChainPath=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
set vtt=x64-windows
:: set vtt=x86-windows
set platform=x64
:: set platform=Win32
set created_test_dir=0
set cmakeMinVersion=3.15
set cmake_batch_debug=0
SET create_shortcut=^
$sln_file = Get-ChildItem %builDir%\*.sln -name;^
$sln_file_parts = $sln_file.Split(\".\");^
$sln_shortcut_name = -join($sln_file_parts[0], '.lnk');^
$sln_file_full_path = -join('%builDir%/', $sln_file);^
$s = (New-Object -COM WScript.Shell).CreateShortcut($sln_shortcut_name);^
$s.TargetPath = $sln_file_full_path;^
$s.Save();
if %cmake_batch_debug% == 0 (
if not exist "%gitDir%" (
choice /M "Create a git repo?"
if !errorlevel! == 1 (
git init
)
)
if not exist "%srcCodeDir%" (
REM You need to use ^ for special chars
echo Creating Source Directory
@mkdir "%srcCodeDir%"
(
echo #include ^<iostream^>
echo:
echo int main^(int argc, char** argv^) {
echo:
echo std::cout ^<^< "Hello World!\n";
echo:
echo }
) > "%srcCodeDir%/main.cpp"
)
if not exist "%testDir%" (
REM You need to use ^ for special chars
REM This is not being set correctly
set created_test_dir = 1
@mkdir "%testDir%"
(
echo #define CATCH_CONFIG_MAIN
echo #include ^<catch2/catch.hpp^>
) > "%testDir%/main.cpp"
(
echo #include ^<catch2/catch.hpp^>
echo:
echo TEST_CASE^("Test1", "[Example]"^) {
echo:
echo }
) > "%testDir%/ExampleTest.cpp"
)
if exist "%builDir%/*.sln" (
CHOICE /M "Solution present. Delete it?"
REM set /p delete_project="Solution present. Delete it?[yes/no default yes]: "
REM if NOT DEFINED delete_project (
if !errorlevel! == 1 (
echo Removing directory
rmdir /S "%builDir%"
)
)
if exist "%rootDir%/.git/*" (
if not exist "%rootDir%/.gitignore" (
echo build/ > .gitignore
)
)
if not exist "%builDir%" mkdir "%builDir%"
)
:: Specifying the source and build dir does not work for whatever reason
:: cmake -S "%srcDir%" -B "%builDir%" -DCMAKE_TOOLCHAIN_FILE="%toolChainPath%" -DVCPKG_TARGET_TRIPLET="%vtt%"
if not exist "%rootDir%/CMakeLists.txt" (
choice /M "There is no CMakeLists.txt file. Create one?"
if !errorlevel! == 1 goto :pname
goto :exit
:pname
set /p project_name="Enter Project name: "
if NOT DEFINED project_name (
echo The name of the project is required
goto :pname
)
:pdesc
set /p project_desc="Enter Project description: "
if NOT DEFINED project_desc (
echo A description is required
goto :pdesc
)
CHOICE /C EL /D E /T 15 /M "Generate exe or lib?"
REM ENSURE THERE ARE NO SPACES
if !errorlevel! == 0 goto :exit
if !errorlevel! == 1 set project_type=exe
if !errorlevel! == 2 (
set project_type=lib
CHOICE /C SD /D S /T 15 /M "Static or Dynamic (shared) library?"
if !errorlevel! == 1 set project_lib_type=static
if !errorlevel! == 2 set project_lib_type=shared
if !errorlevel! == 0 goto :exit
)
set enable_testing=0
CHOICE /C YN /D Y /T 15 /M "Enable testing?"
if !errorlevel! == 1 set enable_testing=1
if !enable_testing! == 0 (
REM this does not work because I am unable to get created_test_dir to be set with the value 1 when I create a test folder
if !created_test_dir! == 1 (
rmdir /s /q %testDir%
)
)
set /p output_file_name="Enter output file name(leave empty to use Project Name): "
if NOT DEFINED output_file_name (
set output_file_name=!project_name!
)
(
echo cmake_minimum_required^(VERSION %cmakeMinVersion% FATAL_ERROR^)
echo project^("!project_name!" DESCRIPTION "!project_desc!" VERSION 0.0.1 LANGUAGES CXX^)
echo:
if !enable_testing! == 1 (
echo include^(CTest^)
echo:
)
echo set^(OUTPUT_FILE !output_file_name!^)
echo:
echo if ^(NOT DEFINED CMAKE_CXX_STANDARD^)
echo set^(CMAKE_CXX_STANDARD 20^)
echo else^(^)
echo if ^(CMAKE_CXX_STANDARD VERSION_LESS 20^)
echo message^(FATAL_ERROR "CMAKE_CXX_STANDARD of 20 or later required."^)
echo endif^(^)
echo endif^(^)
echo if ^(NOT DEFINED CMAKE_CXX_EXTENSIONS^)
echo set^(CMAKE_CXX_EXTENSIONS OFF^)
echo endif^(^)
echo:
echo if ^(MSVC^)
echo add_definitions^(-D_UNICODE -DUNICODE -DWIN32_LEAN_AND_MEAN -DNOMINMAX -DWINVER=0x0A00 -D_WIN32_WINNT=0x0A00^)
echo add_definitions^(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE^)
echo add_definitions^(-D_ATL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS^)
echo endif^(^)
echo:
echo file^(GLOB_RECURSE PROJ_SRC_FILES
echo CONFIGURE_DEPENDS
echo src/*.c* src/*.h*
echo ^)
echo:
echo #To properly set the files in the treeview for MSVC
echo foreach^(source IN LISTS PROJ_SRC_FILES^)
echo get_filename_component^(source_path "${source}" PATH^)
echo string^(REPLACE "${PROJECT_SOURCE_DIR}/" "" source_path_msvc "${source_path}"^)
echo source_group^("${source_path_msvc}" FILES "${source}"^)
echo endforeach^(^)
echo:
if !project_type! == exe (
echo add_executable^(
) else (
echo add_library^(
)
echo ${OUTPUT_FILE}
if !project_type! == lib (
if !project_lib_type! == shared (
echo SHARED
)
)
echo ${PROJ_SRC_FILES}
echo ^)
echo:
echo target_compile_options^(${OUTPUT_FILE}
echo PRIVATE
echo $^<$^<OR:$^<CXX_COMPILER_ID:Clang^>,$^<CXX_COMPILER_ID:AppleClang^>,$^<CXX_COMPILER_ID:GNU^>^>:
echo -Werror -Wall -Wextra^>
echo $^<$^<CXX_COMPILER_ID:MSVC^>:
echo /W4^>
echo ^)
echo:
echo set_property^(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${OUTPUT_FILE}^)
echo:
if !project_type! == lib (
if !project_lib_type! == shared (
echo set^(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS true^)
echo:
)
)
if !enable_testing! == 1 (
echo enable_testing^(^)
echo:
echo file^(GLOB_RECURSE TEST_FILES
echo CONFIGURE_DEPENDS
echo ${PROJECT_SOURCE_DIR}/tests/*.cpp ${PROJECT_SOURCE_DIR}/tests/*.h
echo ^)
echo:
echo add_executable^(tests
echo ${TEST_FILES}
echo ^)
echo:
echo target_include_directories^(tests
echo PUBLIC
echo tests/
echo src/
echo ^)
echo:
echo find_package^(Catch2 CONFIG REQUIRED^)
echo target_link_libraries^(tests
echo PRIVATE
echo Catch2::Catch2
if !project_type! == lib (
echo ${output_file_name}
)
echo ^)
echo:
)
) > "%rootDir%/CMakeLists.txt"
)
:skip
if exist "%rootDir%/CMakeLists.txt" (
echo Executing cmake command
cd "%builDir%"
REM %PROJECTS_INSTALL_DIR% is an environment variable set on my system
cmake .. -DCMAKE_TOOLCHAIN_FILE="%toolChainPath%" -DVCPKG_TARGET_TRIPLET="%vtt%" -DCMAKE_PREFIX_PATH="%PROJECTS_INSTALL_DIR%" -A %platform%
cd "%rootDir%"
choice /t 10 /d y /m "Create solution shortcut in current directory?"
if !errorlevel! == 1 (
echo Creating shortcut
powershell "%create_shortcut%"
)
pause
)
:exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment