Create a Command Line Tool using CMake on Windows
Contents
Create a Command Line Tool using CMake on Windows#
This topic describes the steps needed to configure a CMake project for C++ Command Line Tool. These steps were tested on Windows 11, 23H2. Scripts are PowerShell.
Test that you have all tools installed#
CMake:
cmake --version
ninja:
ninja --version
If you don’t have those tools follow the steps in the Setup C++ development environment on Windows post to configure a C++ development environment.
Create the project directory#
mkdir ~/avblocks/cmake/simple-converter
Create the CMake project#
Switch to the project directory:
cd ~/avblocks/cmake/simple-converter
Add src/main.cpp:
#include <iostream>
int main() {
std::cout << "Hello AVBlocks!\n";
}
Add CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(simple-converter)
add_executable(simple-converter src/main.cpp)
Add .gitignore:
.cache/
build/
Add build.ps1:
New-Item -Force -Path ./build/debug -ItemType Directory
Push-Location ./build/debug
cmake -G 'Ninja' -DCMAKE_BUILD_TYPE=debug ../..
ninja
Pop-Location
Add configure.ps1:
$tempFile = [IO.Path]::GetTempFileName()
# get the path to Visual Studio 2022
$vs_install_dir = $(Get-VSSetupInstance | Select-VSSetupInstance -Version '[17.0,18.0]' | Select-Object -ExpandProperty InstallationPath)
$vs_common_tools = "${vs_install_dir}/Common7/Tools/"
# run VsDevCmd.bat for x64 C++ compiler and save the environment to a file
cmd /c " `"$vs_common_tools/VsDevCmd.bat`" -arch=amd64 -host_arch=amd64 && set > `"$tempFile`""
# set the environment into PowerShell
Get-Content $tempFile | Foreach-Object {
if($_ -match "^(.*?)=(.*)$") {
Set-Content "env:\$($matches[1])" $matches[2]
}
}
Remove-Item $tempFile
You should end up with the following directory structure:
simple-converter
├── .gitignore
├── CMakeLists.txt
├── build.ps1
├── configure.ps1
└── src
└── main.cpp
Test the build#
# source configure.ps1
. .\configure.ps1
# build
./build.ps1
Update for AVBlocks#
Download the 64 bit version of AVBlocks for C++ (Windows). The file you need will have a name similar to
avblocks-v3.1.0-demo.1-windows.zipexcept for the version number which may be different.Extract the archive in a location of your choice, then copy the
includeandlibdirectories to theavblockssubdirectory of the CMake project directory. The CMake project directory is the directory that contains theCMakeLists.txtfile.You should end up with a directory structure similar to the following:
simple-converter ├── .gitignore ├── CMakeLists.txt ├── avblocks │ ├── include │ └── lib ├── build.ps1 ├── configure.ps1 └── src └── main.cppReplace the contents of
.gitignorewith this code:.cache/ build/ avblocks/
Replace the contents of
CMakeLists.txtwith this code:cmake_minimum_required(VERSION 3.16) project(simple-converter) set (target simple-converter) add_executable(${target}) # debug definitions target_compile_definitions(${target} PRIVATE _DEBUG) # debug compile options target_compile_options(${target} PRIVATE /Zi /Od) # enable C++ 17 standard features target_compile_features(${target} PRIVATE cxx_std_17) # include dirs target_include_directories(${target} PRIVATE avblocks/include) # libs target_link_directories(${target} PRIVATE avblocks/lib/x64) target_link_libraries(${target} AVBlocks64.dll) # add /MTd or /MT compiler option set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") # sources file(GLOB source "src/*.cpp") target_sources(${target} PRIVATE ${source})
Replace the contents of
src/main.cppwith this code:#include <primo/avblocks/avb.h> #include <primo/platform/reference++.h> using namespace primo::codecs; using namespace primo::avblocks; int main(int argc, const char * argv[]) { // needed for WMV CoInitializeEx(nullptr, COINITBASE_MULTITHREADED); Library::initialize(); auto inputInfo = primo::make_ref(Library::createMediaInfo()); inputInfo->inputs()->at(0)->setFile(L"Wildlife.wmv"); if (inputInfo->open()) { auto inputSocket = primo::make_ref(Library::createMediaSocket(inputInfo.get())); auto outputSocket = primo::make_ref(Library::createMediaSocket(Preset::Video::Generic::MP4::Base_H264_AAC)); outputSocket->setFile(L"Wildlife.mp4"); auto transcoder = primo::make_ref(Library::createTranscoder()); transcoder->inputs()->add(inputSocket.get()); transcoder->outputs()->add(outputSocket.get()); if (transcoder->open()) { transcoder->run(); transcoder->close(); } } Library::shutdown(); CoUninitialize(); return 0; }
Build the project
. ./configure.ps1 ./build.ps1
Run the application#
Download the
Wildlife.wmvHD movie from the Internet Archive and save it in the project directory.Copy the file
AVBlocks64.dllfromavblocks/lib/x64tobuild/debug.Run the application:
./build/debug/simple-converter
Wait for the Transcoder to finish - it will take a few seconds. The converted file
Wildlife.mp4will be in the project directory.
Troubleshooting#
You may get
The program can't start because AVBlocks64.dll is missing from your computer. Try reinstalling the program to fix this problem.or a similar message. To fix that, copy the fileAVBlocks64.dllfromavblocks/lib/x64tobuild/debug.transcoder->open()may fail if there is already a fileWildlife.mp4in the project directory. DeleteWildlife.mp4to solve that.