Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial CMake build support #252

Merged
merged 23 commits into from
Feb 4, 2025
Merged
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ jobs:
working_directory: ice-demos/cpp
msbuild_project: msbuild/ice.proj

- name: Build C++ Demos on ${{ matrix.os }} with CMake
timeout-minutes: 5
working-directory: ice-demos/cpp
run: cmake -B build -S . && cmake --build build --config Release

- name: Build C# Demos on ${{ matrix.os }}
timeout-minutes: 20
working-directory: ice-demos/csharp
Expand Down
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@
"Make.*": "makefile"
},
"C_Cpp.default.cppStandard": "c++17",
"gradle.nestedProjects": true
"gradle.nestedProjects": true,
"cmake.sourceDirectory": "${workspaceFolder}/cpp",
"cmake.configureSettings": {
"Ice_HOME": "${workspaceFolder}/../ice",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sets the cmake variable Ice_HOME to our usual "expected" location, adjacent to the ice-demos dir. This way you don't need to open visual studio code with the correct environment.

}
}
6 changes: 6 additions & 0 deletions cpp/CMakeLists.txt
externl marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.16)

project(IceDemos CXX)

add_subdirectory(Ice/greeter)
add_subdirectory(Ice/greeterAsync)
15 changes: 15 additions & 0 deletions cpp/Ice/greeter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.16)

project(IceGreeter CXX)
externl marked this conversation as resolved.
Show resolved Hide resolved

include(../../cmake/common.cmake)

add_executable(ice_greeter_client Client.cpp Greeter.ice)
slice2cpp_generate(ice_greeter_client)
set_target_properties(ice_greeter_client PROPERTIES OUTPUT_NAME client)
externl marked this conversation as resolved.
Show resolved Hide resolved
target_link_libraries(ice_greeter_client Ice::Ice)

add_executable(ice_greeter_server Server.cpp ChatBot.cpp ChatBot.h Greeter.ice)
slice2cpp_generate(ice_greeter_server)
set_target_properties(ice_greeter_server PROPERTIES OUTPUT_NAME server)
target_link_libraries(ice_greeter_server Ice::Ice)
30 changes: 30 additions & 0 deletions cpp/Ice/greeterAsync/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.16)

project(IceGreeterAsync CXX)

include(../../cmake/common.cmake)

get_filename_component(greeter_slice "Greeter.ice" ABSOLUTE)

set(slice_output_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
make_directory(${slice_output_dir})

set(greeter_slice_source "${slice_output_dir}/Greeter.cpp")
set(greeter_slice_header "${slice_output_dir}/Greeter.h")

add_custom_command(
OUTPUT "${greeter_slice_source}" "${greeter_slice_header}"
COMMAND ${Ice_SLICE2CPP_EXECUTABLE} --output-dir "${slice_output_dir}" "${greeter_slice}"
DEPENDS "${greeter_slice}"
COMMENT "Compiling ${greeter_slice}"
)

add_executable(ice_greeter_async_client Client.cpp ${greeter_slice_source} ${greeter_slice_header})
externl marked this conversation as resolved.
Show resolved Hide resolved
target_link_libraries(ice_greeter_async_client Ice::Ice)
target_include_directories(ice_greeter_async_client PRIVATE ${slice_output_dir})
set_target_properties(ice_greeter_async_client PROPERTIES OUTPUT_NAME client)

add_executable(ice_greeter_async_server Server.cpp ChatBot.cpp ChatBot.h ${greeter_slice_source} ${greeter_slice_header})
externl marked this conversation as resolved.
Show resolved Hide resolved
target_link_libraries(ice_greeter_async_server Ice::Ice)
target_include_directories(ice_greeter_async_server PRIVATE ${slice_output_dir})
set_target_properties(ice_greeter_async_server PROPERTIES OUTPUT_NAME server)
98 changes: 98 additions & 0 deletions cpp/cmake/common.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
cmake_minimum_required(VERSION 3.16)

if (WIN32)
# Temporary see https://github.com/zeroc-ice/ice/issues/3476
set(CMAKE_CXX_STANDARD 20)
else()
set(CMAKE_CXX_STANDARD 17)
endif()

set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Threads REQUIRED)

if (NOT Ice_HOME)
externl marked this conversation as resolved.
Show resolved Hide resolved
if (DEFINED ENV{ICE_HOME})
set(Ice_HOME $ENV{ICE_HOME} )
else()
message(FATAL_ERROR "Ice_HOME not set")
externl marked this conversation as resolved.
Show resolved Hide resolved
endif()
endif()

if (NOT EXISTS ${Ice_HOME})
message(FATAL_ERROR "The specified Ice_HOME directory does not exist: ${Ice_HOME}")
endif()

find_program(Ice_SLICE2CPP_EXECUTABLE slice2cpp HINTS ${Ice_HOME}/cpp/bin PATH_SUFFIXES x64/Release x64/Debug)
externl marked this conversation as resolved.
Show resolved Hide resolved

if (NOT Ice_SLICE2CPP_EXECUTABLE)
message(FATAL_ERROR "slice2cpp executable not found")
endif()

if (NOT DEFINED Ice_SLICE_DIR)
set(Ice_SLICE_DIR ${Ice_HOME}/slice CACHE PATH "Path to Ice slice files")
endif()

# TODO Use a variable
if (WIN32)
externl marked this conversation as resolved.
Show resolved Hide resolved
set(Ice_INCLUDE_DIRS ${Ice_HOME}/cpp/include ${Ice_HOME}/cpp/include/generated ${Ice_HOME}/cpp/include/generated/x64/Release)
find_library(Ice_LIBRARY NAMES ice38a0 HINTS ${Ice_HOME}/cpp/lib PATH_SUFFIXES x64/Release)
# set(Ice_LIBRARY ${ICE_LIBRARY} PARENT_SCOPE)
elseif(APPLE)
set(Ice_INCLUDE_DIRS ${Ice_HOME}/cpp/include ${Ice_HOME}/cpp/include/generated)
set(Ice_LIBRARY ${Ice_HOME}/cpp/lib/libIce.dylib)
# find_library(Ice_LIBRARY NAMES Ice.dylib HINTS ${Ice_HOME}/cpp/lib/)
# set(Ice_LIBRARY ${ICE_LIBRARY} PARENT_SCOPE)
else()
set(Ice_INCLUDE_DIRS ${Ice_HOME}/cpp/include ${Ice_HOME}/cpp/include/generated)
set(Ice_LIBRARY ${Ice_HOME}/cpp/lib/libIce.so)
endif()

add_library(Ice::Ice SHARED IMPORTED)
set_target_properties(Ice::Ice PROPERTIES IMPORTED_IMPLIB ${Ice_LIBRARY})
set_target_properties(Ice::Ice PROPERTIES
IMPORTED_LOCATION ${Ice_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES "${Ice_INCLUDE_DIRS}"
)

# Function to generate C++ source files from Slice (.ice) files for a target using slice2cpp
# The target must have the Slice files in its sources
# The generated files are added to the target sources
# Usage:
# add_executable(a_target source1.cpp source2.ice source3.ice)
# slice2cpp_generate(a_target)
function(slice2cpp_generate TARGET)

# Get the list of source files for the target
get_target_property(SOURCES ${TARGET} SOURCES)

# Create a directory to store the generated files
set(output_dir ${CMAKE_CURRENT_BINARY_DIR}/generated)
make_directory(${output_dir})

# Add the generated headers files to the target include directories
target_include_directories(${TARGET} PRIVATE ${output_dir})

# Process each Slice (.ice) file in the source list
# 1. Run the slice2cpp command to generate the header and source files
# 2. Add the generated files to the target sources
foreach(SLICE_FILE IN LISTS SOURCES)
externl marked this conversation as resolved.
Show resolved Hide resolved
if(SLICE_FILE MATCHES "\\.ice$")

get_filename_component(SLICE_NAME ${SLICE_FILE} NAME_WE)
get_filename_component(SLICE_FILE_ABS ${SLICE_FILE} ABSOLUTE)
set(output_files ${output_dir}/${SLICE_NAME}.h ${output_dir}/${SLICE_NAME}.cpp)

add_custom_command(
OUTPUT ${output_files}
COMMAND ${Ice_SLICE2CPP_EXECUTABLE} -I${Ice_SLICE_DIR} ${SLICE_FILE_ABS} --output-dir ${output_dir}
DEPENDS ${SLICE_FILE_ABS}
COMMENT "${Ice_SLICE2CPP_EXECUTABLE} ${SLICE_FILE_ABS} -> ${SLICE_NAME}.h ${SLICE_NAME}.cpp"
)

target_sources(${TARGET} PRIVATE ${output_files})

endif()
endforeach()

endfunction()
Loading