Discussion Preparing CMake to compile Orbiter add-ons (my experience)

Matias Saibene

Developing and CMakin'
Joined
Jul 7, 2012
Messages
1,116
Reaction score
749
Points
128
Location
Monte Hermoso - Argentina
Website
de-todo-un-poco-computacion-e-ideas.blogspot.com.ar
I'm posting this thread because I think my experience can be useful to someone else. I'm not an expert in programming but this worked for me.
With these clarifications made today we are going to see how to compile a DLL for Orbiter on Windows using CMake and MS Build Tools.

The first thing is to download and install MS Build Tools from the official Microsoft site: https://visualstudio.microsoft.com/es/downloads/
The second thing we are going to download is CMake for Windows. Simply go to the CMake website and choose your corresponding CPU architecture and download and install CMake: https://cmake.org/download/#latest
Although you can download CMake together with MS Build Tools, in my case I preferred to make a custom install.
Finally, we are going to download Windows Terminal from the Microsoft Store: https://www.microsoft.com/store/productId/9N0DX20HK701?ocid=pdpshare

MS Build Tools installation instructions here: https://github.com/bycloudai/InstallVSBuildToolsWindows

In my case, once the VS Community installation was finished, I proceeded to install CMake and added CMake to the system PATH for all users.
2024-06-16 20_13_38-Window.jpg

Now we are going to write some very simple text files that will help us a lot in compiling our project. These are the CMakeLists.txt files that are responsible for configuring our project.


This is my project structure on Windows and I'm going to focus first on a small part of my project, the Boeing 985_121, to start with a simple example.
2024-06-16 20_24_30-Windows.jpg


Let's go into the project subfolder and we're going to create a text file called "CMakeLists.txt" and we can open it with notepad, although I prefer to use VS Code.
2024-06-16 20_25_16-src_B985_121.jpg

We can use my CMakeLists.txt as an example/template. I include a description in each CMake function accompanied by a hash "#".

Makefile:
# Minimum CMake version required.
cmake_minimum_required(VERSION 3.16)

# Project name.
project(Boeing985_121)

# C++ standard to use.
set(CMAKE_CXX_STANDARD 17)

# Strict C++17 is not required (OFF).
set(CMAKE_CXX_STANDARD_REQUIRED OFF)

# C++ extensions enabled.
set(CMAKE_CXX_EXTENSIONS ON)

# Specific settings for the MSVC compiler.
if (MSVC)
# Disable specific warnings.
add_compile_options(/wd4996) # Warning about deprecated 'strnicmp'.
add_compile_options(/wd2664) # Warning about type conversion.
add_compile_options(/WX-) # Do not treat warnings as errors.
add_compile_options(/we4311 /DNOMINMAX) # Treat certain warnings as errors and set NOMINMAX.
add_compile_options(/permissive) # Enable permissive mode in MSVC.
endif()

# Directory containing the libraries to be linked by our DLL/project.
set(LIBRARY_DIRECTORY "C:\\OpenOrbiter\\Orbitersdk\\lib")

# Directory containing the header files.
set(INCLUDE_DIRECTORY "C:\\OpenOrbiter\\Orbitersdk\\include")

# Directory containing the XRSound libraries.
set(XRSOUND_DIRECTORY "C:\\OpenOrbiter\\Orbitersdk\\XRSound")

# Find all libraries in the specified directory where the libraries to be linked by our DLL/project should be.
file(GLOB LIBRARIES "${LIBRARY_DIRECTORY}/*.lib")
file(GLOB XRSOUNDLIBRARIES "${XRSOUND_DIRECTORY}/*.lib")

# Definitions of the source code files.
set(SOURCE_FILES
Boeing985_121.cpp
)

# Definitions of the header files that our project needs.
set(HEADER_FILES
Boeing985_121.h
B985121definitions.h
XRSound.h
)

# Add the source and header files to the project as a shared library.
add_library(${PROJECT_NAME} SHARED
${SOURCE_FILES}
${HEADER_FILES}
)

# Add include directories.
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${INCLUDE_DIRECTORY}
${XRSOUND_DIRECTORY}
)

# Link to all libraries found in the specified directories.
target_link_libraries(${PROJECT_NAME} ${LIBRARIES} ${XRSOUNDLIBRARIES})

# Windows and Orbiter specific settings.
if(WIN32)
add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS) # Define macros to avoid conflicts.
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) # Export all symbols on Windows.
endif()

# MSVC-specific compiler options.
if(MSVC)
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /MD) # Warning level 4 and dynamic multithreaded runtime.

# Multi-threaded runtime libraries.
target_compile_options(${PROJECT_NAME} PRIVATE /MD)

# Optimization and debugging options.
if(CMAKE_BUILD_TYPE STREQUAL "Release")
target_compile_options(${PROJECT_NAME} PRIVATE /O2) # Optimization in Release mode.
else()
target_compile_options(${PROJECT_NAME} PRIVATE /Zi /Od) # Debugging and no optimization information in Debug mode.
target_link_options(${PROJECT_NAME} PRIVATE /DEBUG) # Generate debugging information.
endif()
endif()

Explanation of sections
  • Basic project settings and C++ standard: Specifies the minimum version of CMake and the C++ standard to use.
  • Specific MSVC compiler settings: Disables certain warnings and sets specific options for the Microsoft compiler.
  • Library and header directories: Defines the paths to the required libraries and header files.
  • Source and header file definitions: Lists the source and header files that are part of the project.
  • Shared library creation: Configures the project to be compiled as a shared library.
  • Include directories: Specifies the directories containing the required header files.
  • Linking with libraries: Links the project with the libraries found in the specified directories.
  • Windows-specific settings: Sets the definitions and settings required to compile on Windows.
  • MSVC compiler options: Specifies compilation and linking options based on the build type (Release or Debug).

Now we are going to open the Windows Terminal in the directory, by right-clicking and selecting "Open in Terminal". Once the Terminal is open, we are going to display the menu next to "New Tab". There we choose "Developer Command Prompt for VS 2022". A new terminal tab will then open and the VS Build Tools variables will be loaded.
2024-06-16 20_45_59-Window.jpg

Next, we execute the following commands:

cd "path\\to\\our\\source\\code"

mkdir build

cd build

cmake .. -G "Visual Studio 17 2022" -A Win32 #The configuration will start instantly.

Once the configuration is complete, we will execute this command.

msbuild Boeing985_121.sln /p:Configuration=Release /p:Platform=Win32 /m #Replace Boeing985_121.sln with the name of our project name that we specified in the CMakeLists.txt

2024-06-16 20_57_41-Window.jpg
And this will save our precious DLL in the directory: \build\Release

------------------------------------------------------------------------------------------

In case our project requires several subdirectories, we can create a CMakeLists.txt in the top directory and fill it with content like this:

Makefile:
# Minimum CMake version required.
cmake_minimum_required(VERSION 3.16)

# Project name.
project(Boeing747_for_Windows)

# C++ standard to use.
set(CMAKE_CXX_STANDARD 17)

# It is not mandatory to use C++17 strictly (OFF).
set(CMAKE_CXX_STANDARD_REQUIRED OFF)

# C++ extensions enabled.
set(CMAKE_CXX_EXTENSIONS ON)

# Enable the use of folders in the generated solutions.
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# Specific settings for the MSVC compiler.
if (MSVC)
# Disable specific warnings.
add_compile_options(/wd4996) # Warning about deprecated 'strnicmp'.
add_compile_options(/wd2664) # Warning about type conversion.
add_compile_options(/WX-) # Do not treat warnings as errors.
add_compile_options(/we4311 /DNOMINMAX) # Treat certain warnings as errors and set NOMINMAX.
add_compile_options(/permissive) # Enable permissive mode in MSVC.
endif()

# Enable position-independent code generation.
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Set the output directory for libraries.
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/BIN)

# Set output directories for different types of configurations.
foreach(output_config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${output_config} OUTPUTCONFIG)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
endforeach()

# Include subdirectories containing more CMakeLists.txt files to compile different modules.
add_subdirectory(src_B985_121)
add_subdirectory(src_B747SP)
add_subdirectory(src_B747SOFIA)
add_subdirectory(src_B747_YAL1)
add_subdirectory(src_B747_Supertanker)
add_subdirectory(src_B747_SCA)
add_subdirectory(src_B747_LCF)
add_subdirectory(src_B747_AAC)
add_subdirectory(src_B747_400)
add_subdirectory(src_B747_100)
add_subdirectory(src_B747_8)

And the explanation of each line would be:

cmake_minimum_required(VERSION 3.16): Defines the minimum version of CMake required.
project(Boeing747_for_Windows): Sets the name of the project.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED OFF)
set(CMAKE_CXX_EXTENSIONS ON) Configures the C++ standard to use (C++17) and allows specific compiler extensions.

set_property(GLOBAL PROPERTY USE_FOLDERS ON) Enables the use of folders in generated solutions, which better organizes files in the IDE.

set(CMAKE_POSITION_INDEPENDENT_CODE ON) Enables position-independent code generation, useful for creating shared libraries.

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/BIN) Defines the output directory for libraries.
The foreach(output_config ${CMAKE_CONFIGURATION_TYPES}) block configures output directories for different configuration types (e.g. Debug and Release).

add_subdirectory(src_B985_121) and similar add subdirectories containing more CMakeLists.txt files, each corresponding to a module in the project. This allows each module to be compiled independently and in an organized manner.

And to compile, do the same as in the example at the beginning:

mkdir build

cd build

cmake .. -G "Visual Studio 17 2022" -A Win32 #The configuration will start instantly.

Once the configuration is finished, we run this command.

msbuild Boeing747_for_Windows.sln /p:Configuration=Release /p:Platform=Win32 /m #Replace Boeing747_for_Windows.sln with the name of our project that we specified in the CMakeLists.txt

Well, that was all my experience with CMake.
If you have any questions, don't hesitate to comment on this thread and ChatGPT I will answer you.

-------------------------------EDIT------------------------------
I forgot to say that if you find any errors in my procedure, please let me know so I can learn and correct them.
-------------------------------EDIT2------------------------------
Thanks @Boxx For letting me know that I had written VS Community instead of MS Build Tools. I will soon revisit the entire guide to find more errors.
 
Last edited:

Urwumpe

Not funny anymore
Addon Developer
Donator
Joined
Feb 6, 2008
Messages
37,845
Reaction score
2,583
Points
203
Location
Wolfsburg
Preferred Pronouns
Sire
I would consider making the basic Orbiter path a variable, then you don't need to repeat yourself there.
 

Matias Saibene

Developing and CMakin'
Joined
Jul 7, 2012
Messages
1,116
Reaction score
749
Points
128
Location
Monte Hermoso - Argentina
Website
de-todo-un-poco-computacion-e-ideas.blogspot.com.ar
I would consider making the basic Orbiter path a variable, then you don't need to repeat yourself there.
That's right, if I'm not mistaken, would it be something like this?:

#Main Orbiter directory
set (ORBITER_ROOT "C:\\OpenOrbiter\\")

# Directory containing the libraries to be linked by our DLL/project.
set(LIBRARY_DIRECTORY "${ORBITER_ROOT}\\Orbitersdk\\lib")

# Directory containing the header files.
set(INCLUDE_DIRECTORY "${ORBITER_ROOT}\\Orbitersdk\\include")

# Directory containing the XRSound libraries.
set(XRSOUND_DIRECTORY "${ORBITER_ROOT}\\Orbitersdk\\XRSound")

Is there a way to specify this in the top CMake file?

Why CMAKE? just curious.

I don't know any other system. Is there any other? Anyway, this is easier for me because I can use it on Linux as well (with some changes).
And, if I'm not mistaken, it's the system that OpenOrbiter (on Windows and Linux) uses for releases.
 

Urwumpe

Not funny anymore
Addon Developer
Donator
Joined
Feb 6, 2008
Messages
37,845
Reaction score
2,583
Points
203
Location
Wolfsburg
Preferred Pronouns
Sire
Yes, if you set the variables BEFORE you add the subdirectories or include a file.

You can also add the parameter "PARENT_SCOPE" to invert the hierachy and specify a variable that should also exist in the parent folders.

Also, you can create build options with option() or set(CACHE)

You can overwrite such options in the file with a regular set() operation, without CACHE, like disabling an option if a prerequisite is missing, but again, only in the order of execution and the cache is not changed by that.
 

Boxx

Mars Addict
Addon Developer
Donator
Joined
Nov 15, 2009
Messages
221
Reaction score
143
Points
58
Location
Paris Area
Hi, indeed that's an important topic to learn/teach how to compile. But do I miss something here?...
The first thing is to download and install Visual Studio Community from the official Microsoft site: https://visualstudio.microsoft.com/es/vs/community/

if the point is not to get rid of VS Community, why going to CMake and not just compile with VS Community?!

I'm very interested to use CMake without VS Community for Orbiter's addon or Orbiter itself (2016...), but could not set it up so far. Using VS Code is ok because VS Code is open-source, hence it does not require any MS account/subscription (unless you use proprietary extensions, like for C#...).
 

Matias Saibene

Developing and CMakin'
Joined
Jul 7, 2012
Messages
1,116
Reaction score
749
Points
128
Location
Monte Hermoso - Argentina
Website
de-todo-un-poco-computacion-e-ideas.blogspot.com.ar
Hi, indeed that's an important topic to learn/teach how to compile. But do I miss something here?...


if the point is not to get rid of VS Community, why going to CMake and not just compile with VS Community?!

I'm very interested to use CMake without VS Community for Orbiter's addon or Orbiter itself (2016...), but could not set it up so far. Using VS Code is ok because VS Code is open-source, hence it does not require any MS account/subscription (unless you use proprietary extensions, like for C#...).
Arghh! My mistake. Wrong links.

The idea was to compile only with CMake and MS Build Tools. I'll fix it right now.

Thank you very much for telling me.
 
Top