Ver3.0 ๐ C++ ํฌ๋ก์ค ์ปดํ์ผ๊ณผ ๋ค์ํ ํ๋ซํผ ๋์ ๋น๋ ํ๊ฒฝ ๊ตฌ์ฑ

๐ C++ ํฌ๋ก์ค ์ปดํ์ผ๊ณผ ๋ค์ํ ํ๋ซํผ ๋์ ๋น๋ ํ๊ฒฝ ๊ตฌ์ฑ
ํ ๋ฒ์ ์ฝ๋๋ก ๋ชจ๋ ํ๋ซํผ์ ์ ๋ณตํ๋ ๋ง๋ฒ ๊ฐ์ ์ฌ์
์๋ ! ์ค๋์ C++ ๊ฐ๋ฐ์๋ผ๋ฉด ํ ๋ฒ์ฏค์ ๊ณ ๋ฏผํด๋ดค์ ์ฃผ์ , ๋ฐ๋ก ํฌ๋ก์ค ์ปดํ์ผ๊ณผ ๋ฉํฐ ํ๋ซํผ ๋น๋ ํ๊ฒฝ ๊ตฌ์ฑ์ ๋ํด ์ด์ผ๊ธฐํด๋ณด๋ ค๊ณ ํด. ๐ฏ
์์ํด๋ด. ๋๊ฐ ๋ง๋ ๋ฉ์ง C++ ํ๋ก๊ทธ๋จ์ด Windows์์๋ง ๋์๊ฐ๋ค๋ฉด? ๋งฅ ์ฌ์ฉ์๋ค์ "๋๋ ์ฐ๊ณ ์ถ์๋ฐ..."๋ผ๋ฉฐ ์์ฌ์ํ ๊ฑฐ์ผ. ๋ฆฌ๋ ์ค ์๋ฒ์ ๋ฐฐํฌํ๋ ค๋ฉด ๋ ๋ค์ ์ฒ์๋ถํฐ? ์๋์ผ, ๊ทธ๋ด ํ์ ์์ด! ํฌ๋ก์ค ์ปดํ์ผ์ ๋ง์คํฐํ๋ฉด ํ ๋ฒ์ ์ฝ๋ ์์ฑ์ผ๋ก ์ฌ๋ฌ ํ๋ซํผ์ ๋์์ ๊ณต๋ตํ ์ ์๊ฑฐ๋ . ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ๊ณต์ ํ๋ฏ์ด, ๋์ ์ฝ๋๋ ์ฌ๋ฌ ํ๋ซํผ์์ ์์ ๋กญ๊ฒ ๊ณต์ ๋ ์ ์๋ ๊ฑฐ์ง! ๐
๐ก ์ ํฌ๋ก์ค ์ปดํ์ผ์ด ์ค์ํ ๊น?
ํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ ํ๊ฒฝ์์๋ ๋จ์ผ ํ๋ซํผ๋ง ์ง์ํ๋ ๊ฒ์ ๊ฒฝ์๋ ฅ์ด ๋จ์ด์ ธ. IoT ๋๋ฐ์ด์ค, ๋ชจ๋ฐ์ผ, ๋ฐ์คํฌํฑ, ์๋ฒ๊น์ง ๋ค์ํ ํ๊ฒฝ์์ ๋์ํด์ผ ํ๋ ์๋๋๊น. ํฌ๋ก์ค ์ปดํ์ผ์ ์ ํ์ด ์๋ ํ์๊ฐ ๋์ด๊ฐ๊ณ ์์ด!
๐จ ํฌ๋ก์ค ์ปดํ์ผ์ ๊ธฐ๋ณธ ๊ฐ๋ ์ดํดํ๊ธฐ
๋จผ์ ํฌ๋ก์ค ์ปดํ์ผ์ด ๋ญ์ง๋ถํฐ ํ์คํ ์ง๊ณ ๋์ด๊ฐ์. ํฌ๋ก์ค ์ปดํ์ผ(Cross Compilation)์ ๋ง ๊ทธ๋๋ก "๊ต์ฐจ ์ปดํ์ผ"์ด์ผ. ์ฆ, ํ์ฌ ์์ ํ๊ณ ์๋ ํ๋ซํผ(ํธ์คํธ)๊ณผ ๋ค๋ฅธ ํ๋ซํผ(ํ๊ฒ)์ ์ํ ์คํ ํ์ผ์ ๋ง๋๋ ๊ณผ์ ์ด์ง.
์๋ฅผ ๋ค์ด๋ณผ๊น? ๋๊ฐ Windows PC์์ ๊ฐ๋ฐํ๊ณ ์๋๋ฐ, ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด(ARM ์ํคํ ์ฒ)์์ ๋์๊ฐ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด์ผ ํ๋ค๋ฉด? ์ผ๋ฐ์ ์ธ ์ปดํ์ผ์ Windows์ฉ ์คํ ํ์ผ(.exe)์ ๋ง๋ค์ง๋ง, ํฌ๋ก์ค ์ปดํ์ผ์ ์ฌ์ฉํ๋ฉด ARM ์ํคํ ์ฒ์ฉ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ง๋ค ์ ์์ด. ๐ฏ
๐ ํต์ฌ ์ฉ์ด ์ ๋ฆฌ
ํธ์คํธ(Host): ์ปดํ์ผ์ ์คํํ๋ ์์คํ
(์: ๋์ ๊ฐ๋ฐ PC)
ํ๊ฒ(Target): ์ปดํ์ผ๋ ํ๋ก๊ทธ๋จ์ด ์คํ๋ ์์คํ
(์: ์๋ฒ ๋๋ ๋๋ฐ์ด์ค)
๋น๋(Build): ์ปดํ์ผ๋ฌ๊ฐ ์คํ๋๋ ์์คํ
(๋๋ถ๋ถ ํธ์คํธ์ ๋์ผ)
ํด์ฒด์ธ(Toolchain): ์ปดํ์ผ๋ฌ, ๋ง์ปค, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ ๋น๋์ ํ์ํ ๋๊ตฌ ๋ชจ์
๐ ๏ธ ํฌ๋ก์ค ์ปดํ์ผ ํ๊ฒฝ ๊ตฌ์ฑ์ ์ค์ ๋จ๊ณ
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ํฌ๋ก์ค ์ปดํ์ผ ํ๊ฒฝ์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์. ์ฒ์์๋ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ๋จ๊ณ๋ณ๋ก ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐ๋ผ์ค๋ฉด ์๊ฐ๋ณด๋ค ์ด๋ ต์ง ์์! ๐
Step 1: ํ๊ฒ ํ๋ซํผ ๊ฒฐ์ ํ๊ธฐ ๐
๊ฐ์ฅ ๋จผ์ ํด์ผ ํ ์ผ์ ์ด๋ค ํ๋ซํผ์ ํ๊ฒ์ผ๋ก ํ ๊ฒ์ธ์ง ๋ช ํํ ์ ํ๋ ๊ฑฐ์ผ. ๊ฐ ํ๋ซํผ๋ง๋ค ํ์ํ ํด์ฒด์ธ๊ณผ ์ค์ ์ด ๋ค๋ฅด๊ฑฐ๋ .
๐ช Windows ํ๊ฒ
์ํคํ
์ฒ: x86, x86_64, ARM64
์ฃผ์ ์ปดํ์ผ๋ฌ: MinGW, MSVC
ํน์ง: DLL ์์กด์ฑ ๊ด๋ฆฌ ์ค์
๐ง Linux ํ๊ฒ
์ํคํ
์ฒ: x86_64, ARM, ARM64
์ฃผ์ ์ปดํ์ผ๋ฌ: GCC, Clang
ํน์ง: ๋ค์ํ ๋ฐฐํฌํ ๊ณ ๋ ค ํ์
๐ macOS ํ๊ฒ
์ํคํ
์ฒ: x86_64, ARM64(M1/M2)
์ฃผ์ ์ปดํ์ผ๋ฌ: Clang (Apple Clang)
ํน์ง: ์ ๋๋ฒ์ค ๋ฐ์ด๋๋ฆฌ ์ง์
๐ฑ ๋ชจ๋ฐ์ผ/์๋ฒ ๋๋
์ํคํ
์ฒ: ARM, ARM64, MIPS
์ฃผ์ ์ปดํ์ผ๋ฌ: ARM GCC, NDK
ํน์ง: ๋ฆฌ์์ค ์ ์ฝ ๊ณ ๋ ค
Step 2: ์ ์ ํ ํด์ฒด์ธ ์ ํ ๋ฐ ์ค์น ๐ง
ํด์ฒด์ธ์ ํฌ๋ก์ค ์ปดํ์ผ์ ํต์ฌ์ด์ผ. ํ๊ฒ ํ๋ซํผ์ ๋ง๋ ์ปดํ์ผ๋ฌ, ๋ง์ปค, ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ชจ๋ ํฌํจ๋์ด ์์ด์ผ ํด.
๐ฏ ์ฃผ์ ํฌ๋ก์ค ์ปดํ์ผ ํด์ฒด์ธ
1. GNU ํด์ฒด์ธ (GCC ๊ธฐ๋ฐ)
๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์คํ์์ค ํด์ฒด์ธ์ด์ผ. ๊ฑฐ์ ๋ชจ๋ ํ๋ซํผ์ ์ง์ํ๊ณ , ์์ ์ฑ์ด ๊ฒ์ฆ๋์ด ์์ด.
# ARM Linux์ฉ GCC ํด์ฒด์ธ ์ค์น (Ubuntu/Debian)
sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
# ARM64์ฉ ํด์ฒด์ธ
sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
# Windows์ฉ MinGW ํด์ฒด์ธ
sudo apt-get install mingw-w64
2. LLVM/Clang ํด์ฒด์ธ
๋ชจ๋ํ๊ณ ๋น ๋ฅธ ์ปดํ์ผ ์๋๋ฅผ ์๋ํด. ํนํ macOS์ iOS ๊ฐ๋ฐ์๋ ํ์์ ์ด์ง.
# Clang ์ค์น
sudo apt-get install clang
# ํฌ๋ก์ค ์ปดํ์ผ ์ ํ๊ฒ ์ง์
clang++ --target=arm-linux-gnueabihf -o output main.cpp
3. ํ๋ซํผ ํนํ ํด์ฒด์ธ
ํน์ ํ๋ซํผ์ ์ํ ์ ์ฉ ํด์ฒด์ธ๋ ์์ด. Android NDK, iOS SDK, Raspberry Pi ํด์ฒด์ธ ๋ฑ์ด ๋ํ์ ์ด์ผ.
๐ก Pro Tip: ํด์ฒด์ธ ๋ฒ์ ๊ด๋ฆฌ
์ฌ๋ฌ ํ๋ก์ ํธ๋ฅผ ๋์์ ์งํํ๋ค๋ฉด ํด์ฒด์ธ ๋ฒ์ ๊ด๋ฆฌ๊ฐ ์ ๋ง ์ค์ํด! ํ๋ก์ ํธ๋ง๋ค ์๊ตฌํ๋ ์ปดํ์ผ๋ฌ ๋ฒ์ ์ด ๋ค๋ฅผ ์ ์๊ฑฐ๋ . Docker๋ ๊ฐ์ํ๊ฒฝ์ ํ์ฉํ๋ฉด ๋ฒ์ ์ถฉ๋ ์์ด ๊น๋ํ๊ฒ ๊ด๋ฆฌํ ์ ์์ด. ๐ณ
๐๏ธ CMake๋ฅผ ํ์ฉํ ํฌ๋ก์ค ํ๋ซํผ ๋น๋ ์์คํ
์, ์ด์ ์ค์ ์ผ๋ก ๋ค์ด๊ฐ๋ณด์! ํ๋์ ์ธ C++ ํ๋ก์ ํธ์์๋ CMake๊ฐ ์ฌ์ค์ ํ์ค์ด์ผ. CMake๋ ํ๋ซํผ ๋ ๋ฆฝ์ ์ธ ๋น๋ ์์คํ ์ ๊ตฌ์ถํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฐ๋ ฅํ ๋๊ตฌ๊ฑฐ๋ . ์ฌ๋ฅ๋ท์์ ๋ค์ํ ๊ฐ๋ฐ์๋ค์ด ํ๋ก์ ํธ๋ฅผ ๊ณต์ ํ ๋๋ CMake๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ตฌ๋ ์ฝ๊ฒ ๋น๋ํ ์ ์์ด! ๐จ
๐ ๊ธฐ๋ณธ CMakeLists.txt ๊ตฌ์กฐ
cmake_minimum_required(VERSION 3.15)
project(CrossPlatformApp VERSION 1.0.0 LANGUAGES CXX)
# C++ ํ์ค ์ค์
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ์์ค ํ์ผ ์ ์
set(SOURCES
src/main.cpp
src/utils.cpp
src/platform_specific.cpp
)
# ์คํ ํ์ผ ์์ฑ
add_executable(${PROJECT_NAME} ${SOURCES})
# ํ๋ซํผ๋ณ ์ค์
if(WIN32)
target_compile_definitions(${PROJECT_NAME} PRIVATE PLATFORM_WINDOWS)
elseif(APPLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE PLATFORM_MACOS)
elseif(UNIX)
target_compile_definitions(${PROJECT_NAME} PRIVATE PLATFORM_LINUX)
endif()
# ์ปดํ์ผ ์ต์
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic>
)
โ ๏ธ ์ฃผ์์ฌํญ: ํ๋ซํผ๋ณ ์ฐจ์ด์
๊ฐ ํ๋ซํผ๋ง๋ค ํ์ผ ์์คํ ๊ฒฝ๋ก ๊ตฌ๋ถ์, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ฅ์, ์คํ ํ์ผ ํ์์ด ๋ฌ๋ผ. Windows๋ ์ญ์ฌ๋์(\)์ .dll, Linux๋ ์ฌ๋์(/)์ .so, macOS๋ .dylib๋ฅผ ์ฌ์ฉํ์ง. CMake์ ํ๋ซํผ ๋ณ์๋ฅผ ํ์ฉํ๋ฉด ์ด๋ฐ ์ฐจ์ด๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ด!
๐ฏ ํฌ๋ก์ค ์ปดํ์ผ์ ์ํ Toolchain ํ์ผ
CMake์์ ํฌ๋ก์ค ์ปดํ์ผ์ ํ๋ ค๋ฉด ํด์ฒด์ธ ํ์ผ์ ์์ฑํด์ผ ํด. ์ด ํ์ผ์๋ ํ๊ฒ ์์คํ ์ ๋ณด์ ์ปดํ์ผ๋ฌ ๊ฒฝ๋ก๊ฐ ๋ด๊ฒจ ์์ด.
# arm-linux-toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# ํฌ๋ก์ค ์ปดํ์ผ๋ฌ ๊ฒฝ๋ก ์ง์
set(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++)
# ํ๊ฒ ์์คํ
์ ๋ฃจํธ ๋๋ ํ ๋ฆฌ
set(CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabihf)
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฒ์ ๋ชจ๋
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# ์ถ๊ฐ ์ปดํ์ผ ํ๋๊ทธ
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfpu=neon")
์ด ํด์ฒด์ธ ํ์ผ์ ์ฌ์ฉํด์ ๋น๋ํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์คํํ๋ฉด ๋ผ:
mkdir build-arm
cd build-arm
cmake -DCMAKE_TOOLCHAIN_FILE=../arm-linux-toolchain.cmake ..
make
๐ ์ค์ ์์ : ๋ฉํฐ ํ๋ซํผ ๋น๋ ์คํฌ๋ฆฝํธ
์ค๋ฌด์์๋ ์ฌ๋ฌ ํ๋ซํผ์ ํ ๋ฒ์ ๋น๋ํด์ผ ํ ๋๊ฐ ๋ง์. ์๋ํ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์ด๋๋ฉด ์ ๋ง ํธ๋ฆฌํ์ง!
#!/bin/bash
# build_all.sh - ๋ชจ๋ ํ๋ซํผ ๋น๋ ์คํฌ๋ฆฝํธ
PLATFORMS=("linux-x64" "linux-arm" "windows-x64" "macos-arm64")
for platform in "${PLATFORMS[@]}"; do
echo "Building for $platform..."
mkdir -p build-$platform
cd build-$platform
case $platform in
"linux-x64")
cmake ..
;;
"linux-arm")
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux.cmake ..
;;
"windows-x64")
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/mingw-w64.cmake ..
;;
"macos-arm64")
cmake -DCMAKE_OSX_ARCHITECTURES=arm64 ..
;;
esac
make -j$(nproc)
cd ..
done
echo "All builds completed!"
๐ ํ๋ซํผ๋ณ ํน์ ๊ณ ๋ ค์ฌํญ
๊ฐ ํ๋ซํผ๋ง๋ค ๋ ํนํ ํน์ฑ๊ณผ ์ ์ฝ์ฌํญ์ด ์์ด. ์ด๊ฑธ ์ ๋๋ก ์ดํดํ๊ณ ๋์ํด์ผ ์ง์ ํ ํฌ๋ก์ค ํ๋ซํผ ๊ฐ๋ฐ์๊ฐ ๋ ์ ์์ง! ๐
๐ช Windows ํ๋ซํผ ๋น๋
Windows๋ ๋ค๋ฅธ ํ๋ซํผ๊ณผ ๋น๊ตํ์ ๋ ๋ช ๊ฐ์ง ๋ ํนํ ์ ์ด ์์ด:
1. ๋ฐํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ํ
MSVC๋ฅผ ์ฌ์ฉํ ๋๋ ๋ฐํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋งํฌ ๋ฐฉ์์ ์ ํํด์ผ ํด. ์ ์ ๋งํฌ(/MT)์ ๋์ ๋งํฌ(/MD) ์ค ํ๋๋ฅผ ๊ณจ๋ผ์ผ ํ๋๋ฐ, ์ด๊ฒ ํ๋ก์ ํธ ์ ์ฒด์ ์ผ๊ด๋๊ฒ ์ ์ฉ๋์ด์ผ ํด.
# CMake์์ ๋ฐํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์
if(MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
2. DLL ์์กด์ฑ ๊ด๋ฆฌ
Windows์์๋ ์คํ ํ์ผ๊ณผ ๊ฐ์ ๋๋ ํ ๋ฆฌ๋ ์์คํ PATH์ DLL์ด ์์ด์ผ ํด. ๋ฐฐํฌํ ๋ ํ์ํ DLL์ ๋ชจ๋ ํฌํจ์์ผ์ผ ํ๋ค๋ ์ , ์์ง ๋ง!
# ํ์ํ DLL ๋ณต์ฌ (CMake)
if(WIN32)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/libs/external.dll"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
endif()
3. ๊ฒฝ๋ก ๊ตฌ๋ถ์ ์ฒ๋ฆฌ
Windows๋ ๋ฐฑ์ฌ๋์(\)๋ฅผ ์ฌ์ฉํ์ง๋ง, C++ ์ฝ๋์์๋ ์ฌ๋์(/)๋ ์ ์๋ํด. ํ์ง๋ง std::filesystem์ ์ฌ์ฉํ๋ฉด ํ๋ซํผ ๋ ๋ฆฝ์ ์ผ๋ก ๊ฒฝ๋ก๋ฅผ ๋ค๋ฃฐ ์ ์์ด!
#include <filesystem>
namespace fs = std::filesystem;
// ํ๋ซํผ ๋
๋ฆฝ์ ๊ฒฝ๋ก ์ฒ๋ฆฌ
fs::path config_path = fs::current_path() / "config" / "settings.ini";
std::cout << config_path.string() << std::endl;
๐ง Linux ํ๋ซํผ ๋น๋
Linux๋ ์คํ์์ค ์ํ๊ณ์ ์ค์ฌ์ด๋ผ ๊ฐ๋ฐ ๋๊ตฌ๊ฐ ํ๋ถํ์ง๋ง, ๋ฐฐํฌํ๋ง๋ค ์ฐจ์ด๊ฐ ์์ด ์ฃผ์๊ฐ ํ์ํด.
1. ๋ฐฐํฌํ๋ณ ์ฐจ์ด
Ubuntu, Fedora, Arch Linux ๋ฑ ๋ฐฐํฌํ๋ง๋ค ๊ธฐ๋ณธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ์ด ๋ฌ๋ผ. ์ ์ ๋งํฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ AppImage ๊ฐ์ ํฌ๋งท์ ํ์ฉํ๋ฉด ํธํ์ฑ ๋ฌธ์ ๋ฅผ ์ค์ผ ์ ์์ด.
# ์ ์ ๋งํฌ ์ต์
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
# ๋๋ ์์ ์ ์ ๋น๋
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
2. RPATH ์ค์
๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋๋ RPATH๋ฅผ ์ ๋๋ก ์ค์ ํด์ผ ํด. ์ด๊ฒ ์์ผ๋ฉด ์คํ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์ง ๋ชปํ ์ ์์ด.
# CMake RPATH ์ค์
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
3. ๊ถํ ๋ฐ ์คํ ์์ฑ
Linux์์๋ ์คํ ํ์ผ์ ์คํ ๊ถํ์ด ํ์ํด. ๋ฐฐํฌ ์ ์ด ์ ์ ๊ณ ๋ คํด์ผ ํ์ง.
# ์ค์น ์ ์คํ ๊ถํ ๋ถ์ฌ
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
GROUP_EXECUTE GROUP_READ
WORLD_EXECUTE WORLD_READ
)
๐ macOS ํ๋ซํผ ๋น๋
macOS๋ ํนํ M1/M2 ์นฉ ๋์ ์ดํ ARM64 ์ํคํ ์ฒ ์ง์์ด ์ค์ํด์ก์ด.
1. ์ ๋๋ฒ์ค ๋ฐ์ด๋๋ฆฌ
Intel(x86_64)๊ณผ Apple Silicon(ARM64) ๋ชจ๋๋ฅผ ์ง์ํ๋ ์ ๋๋ฒ์ค ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ง๋ค ์ ์์ด.
# ์ ๋๋ฒ์ค ๋ฐ์ด๋๋ฆฌ ๋น๋
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
# ๋๋ ๊ฐ๋ณ ๋น๋ ํ lipo๋ก ํฉ์น๊ธฐ
# lipo -create -output app_universal app_x86_64 app_arm64
2. ์ฝ๋ ์๋ช ๋ฐ ๊ณต์ฆ
macOS 10.15 ์ด์์์๋ ์ฑ ๋ฐฐํฌ ์ ์ฝ๋ ์๋ช ๊ณผ ๊ณต์ฆ(Notarization)์ด ํ์ํด. ์ด๊ฒ ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ ์คํํ ๋ ๊ฒฝ๊ณ ๊ฐ ๋จ๊ฑฐ๋ .
# ์ฝ๋ ์๋ช
(๊ฐ๋ฐ์ ์ธ์ฆ์ ํ์)
codesign --force --deep --sign "Developer ID Application: Your Name" YourApp.app
# ๊ณต์ฆ ์ ์ถ
xcrun altool --notarize-app --file YourApp.zip \
--primary-bundle-id "com.yourcompany.yourapp" \
--username "your@email.com" --password "@keychain:AC_PASSWORD"
3. ํ๋ ์์ํฌ ์์กด์ฑ
macOS๋ ์์คํ ํ๋ ์์ํฌ๋ฅผ ๋ง์ด ์ฌ์ฉํด. CMake์์ ์ด๋ฅผ ์ฝ๊ฒ ๋งํฌํ ์ ์์ด.
if(APPLE)
find_library(COCOA_LIBRARY Cocoa)
find_library(IOKIT_LIBRARY IOKit)
target_link_libraries(${PROJECT_NAME}
${COCOA_LIBRARY}
${IOKIT_LIBRARY}
)
endif()
๐ฏ ์ค์ ํ๋ก์ ํธ ๊ตฌ์กฐ ์ค๊ณ
์ด๋ก ์ ์ถฉ๋ถํ ๋ฐฐ์ ์ผ๋, ์ด์ ์ค์ ๋ก ์ด๋ป๊ฒ ํ๋ก์ ํธ๋ฅผ ๊ตฌ์กฐํํ๋์ง ์์๋ณด์! ์ข์ ํ๋ก์ ํธ ๊ตฌ์กฐ๋ ์ ์ง๋ณด์๋ฅผ ์ฝ๊ฒ ๋ง๋ค๊ณ , ์๋ก์ด ํ๋ซํผ ์ถ๊ฐ๋ ๊ฐํธํ๊ฒ ํด์ค. ๐๏ธ
๐ ๊ถ์ฅ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ
MyProject/
โโโ CMakeLists.txt # ๋ฃจํธ CMake ํ์ผ
โโโ README.md
โโโ LICENSE
โโโ .gitignore
โ
โโโ src/ # ์์ค ์ฝ๋
โ โโโ main.cpp
โ โโโ core/ # ํต์ฌ ๋ก์ง (ํ๋ซํผ ๋
๋ฆฝ์ )
โ โ โโโ engine.cpp
โ โ โโโ engine.h
โ โโโ platform/ # ํ๋ซํผ๋ณ ๊ตฌํ
โ โโโ windows/
โ โ โโโ window_impl.cpp
โ โโโ linux/
โ โ โโโ window_impl.cpp
โ โโโ macos/
โ โโโ window_impl.cpp
โ
โโโ include/ # ๊ณต๊ฐ ํค๋ ํ์ผ
โ โโโ myproject/
โ โโโ api.h
โ
โโโ libs/ # ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
โ โโโ external_lib1/
โ โโโ external_lib2/
โ
โโโ toolchains/ # ํฌ๋ก์ค ์ปดํ์ผ ํด์ฒด์ธ ํ์ผ
โ โโโ arm-linux.cmake
โ โโโ mingw-w64.cmake
โ โโโ android-ndk.cmake
โ
โโโ scripts/ # ๋น๋ ๋ฐ ๋ฐฐํฌ ์คํฌ๋ฆฝํธ
โ โโโ build_all.sh
โ โโโ package.sh
โ โโโ deploy.py
โ
โโโ tests/ # ํ
์คํธ ์ฝ๋
โ โโโ unit_tests/
โ โโโ integration_tests/
โ
โโโ docs/ # ๋ฌธ์
โโโ build_instructions.md
โโโ api_reference.md
๐ก ํ๋ซํผ ์ถ์ํ ํจํด
ํ๋ซํผ๋ณ ์ฝ๋๋ฅผ ๊น๋ํ๊ฒ ๋ถ๋ฆฌํ๋ ค๋ฉด ์ถ์ํ ๋ ์ด์ด๋ฅผ ๋ง๋๋ ๊ฒ ์ข์. ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ณ , ๊ฐ ํ๋ซํผ์์ ์ด๋ฅผ ๊ตฌํํ๋ ๋ฐฉ์์ด์ง.
// platform_interface.h
class IPlatformWindow {
public:
virtual ~IPlatformWindow() = default;
virtual bool create(int width, int height) = 0;
virtual void show() = 0;
virtual void update() = 0;
};
// ํฉํ ๋ฆฌ ํจ์
std::unique_ptr<IPlatformWindow> createPlatformWindow();
// windows_window.cpp
#ifdef _WIN32
class WindowsWindow : public IPlatformWindow {
// Windows ํนํ ๊ตฌํ
};
std::unique_ptr<IPlatformWindow> createPlatformWindow() {
return std::make_unique<WindowsWindow>();
}
#endif
// linux_window.cpp
#ifdef __linux__
class LinuxWindow : public IPlatformWindow {
// Linux ํนํ ๊ตฌํ
};
std::unique_ptr<IPlatformWindow> createPlatformWindow() {
return std::make_unique<LinuxWindow>();
}
#endif
๐ง ์กฐ๊ฑด๋ถ ์ปดํ์ผ ํ์ฉํ๊ธฐ
ํ๋ซํผ๋ณ๋ก ๋ค๋ฅธ ์ฝ๋๋ฅผ ์คํํด์ผ ํ ๋๋ ์ ์ฒ๋ฆฌ๊ธฐ ๋งคํฌ๋ก๋ฅผ ํ์ฉํด. ํ์ง๋ง ๋๋ฌด ๋จ์ฉํ๋ฉด ์ฝ๋๊ฐ ์ง์ ๋ถํด์ง๋ ์ฃผ์ํด์ผ ํด!
// platform_detection.h
#ifndef PLATFORM_DETECTION_H
#define PLATFORM_DETECTION_H
// ํ๋ซํผ ๊ฐ์ง
#if defined(_WIN32) || defined(_WIN64)
#define PLATFORM_WINDOWS
#ifdef _WIN64
#define PLATFORM_WINDOWS_64
#else
#define PLATFORM_WINDOWS_32
#endif
#elif defined(__APPLE__) || defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_OS_MAC
#define PLATFORM_MACOS
#elif TARGET_OS_IPHONE
#define PLATFORM_IOS
#endif
#elif defined(__linux__)
#define PLATFORM_LINUX
#if defined(__ANDROID__)
#define PLATFORM_ANDROID
#endif
#elif defined(__unix__)
#define PLATFORM_UNIX
#endif
// ์ํคํ
์ฒ ๊ฐ์ง
#if defined(__x86_64__) || defined(_M_X64)
#define ARCH_X64
#elif defined(__i386) || defined(_M_IX86)
#define ARCH_X86
#elif defined(__aarch64__) || defined(_M_ARM64)
#define ARCH_ARM64
#elif defined(__arm__) || defined(_M_ARM)
#define ARCH_ARM
#endif
// ์ปดํ์ผ๋ฌ ๊ฐ์ง
#if defined(__clang__)
#define COMPILER_CLANG
#elif defined(__GNUC__) || defined(__GNUG__)
#define COMPILER_GCC
#elif defined(_MSC_VER)
#define COMPILER_MSVC
#endif
#endif // PLATFORM_DETECTION_H
์ด์ ์ด ํค๋๋ฅผ ํฌํจํ๋ฉด ์ด๋์๋ ํ๋ซํผ์ ํ์ธํ ์ ์์ด:
#include "platform_detection.h"
void initializeSystem() {
#ifdef PLATFORM_WINDOWS
// Windows ์ด๊ธฐํ
initWinSock();
#elif defined(PLATFORM_LINUX)
// Linux ์ด๊ธฐํ
initPosixSignals();
#elif defined(PLATFORM_MACOS)
// macOS ์ด๊ธฐํ
initCocoaApp();
#endif
}
๐ฆ ์์กด์ฑ ๊ด๋ฆฌ์ ํจํค์ง ๋งค๋์
ํฌ๋ก์ค ํ๋ซํผ ๊ฐ๋ฐ์์ ๊ฐ์ฅ ๊ณจ์น ์ํ ๋ถ๋ถ ์ค ํ๋๊ฐ ๋ฐ๋ก ์์กด์ฑ ๊ด๋ฆฌ์ผ. ๊ฐ ํ๋ซํผ๋ง๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฐ๋ก ๋น๋ํ๊ณ ๊ด๋ฆฌํ๋ ๊ฑด ์ ๋ง ๋ฒ๊ฑฐ๋ก์ด ์ผ์ด๊ฑฐ๋ . ๋คํํ ํ๋์ ์ธ ๋๊ตฌ๋ค์ด ์ด ๋ฌธ์ ๋ฅผ ๋ง์ด ํด๊ฒฐํด์ค! ๐
๐น Conan ํจํค์ง ๋งค๋์
Conan์ C/C++๋ฅผ ์ํ ๊ฐ๋ ฅํ ํจํค์ง ๋งค๋์ ์ผ. Python์ pip๋ Node.js์ npm์ฒ๋ผ ์์กด์ฑ์ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ค.
์ค์น ๋ฐ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ:
# Conan ์ค์น
pip install conan
# ํ๋กํ์ผ ๊ฐ์ง
conan profile detect --force
# conanfile.txt ์์ฑ
[requires]
boost/1.81.0
openssl/3.1.0
fmt/9.1.0
[generators]
CMakeDeps
CMakeToolchain
[options]
boost:shared=False
openssl:shared=True
CMakeLists.txt์์ Conan ํตํฉ:
cmake_minimum_required(VERSION 3.15)
project(MyProject)
# Conan์ผ๋ก ์ค์นํ ์์กด์ฑ ์ฐพ๊ธฐ
find_package(Boost REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(fmt REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp
Boost::boost
OpenSSL::SSL
fmt::fmt
)
ํฌ๋ก์ค ์ปดํ์ผ ์ Conan ํ๋กํ์ผ ์ฌ์ฉ:
# arm-linux-profile
[settings]
os=Linux
arch=armv7
compiler=gcc
compiler.version=11
compiler.libcxx=libstdc++11
build_type=Release
[buildenv]
CC=arm-linux-gnueabihf-gcc
CXX=arm-linux-gnueabihf-g++
# ํ๋กํ์ผ ์ฌ์ฉํด์ ์์กด์ฑ ์ค์น
conan install . --profile=arm-linux-profile --build=missing
๐น vcpkg ํจํค์ง ๋งค๋์
Microsoft๊ฐ ๋ง๋ vcpkg๋ ํ๋ฅญํ ์ ํ์ง์ผ. ํนํ Windows ๊ฐ๋ฐ์๋ค์๊ฒ ์น์ํ๊ณ , CMake์์ ํตํฉ์ด ๋งค๋๋ฌ์.
# vcpkg ์ค์น (Linux/macOS)
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
./vcpkg install boost:x64-linux
./vcpkg install openssl:x64-linux
./vcpkg install fmt:x64-linux
# ํฌ๋ก์ค ์ปดํ์ผ์ฉ ํธ๋ฆฌํ๋
./vcpkg install boost:arm-linux
./vcpkg install boost:x64-windows
./vcpkg install boost:arm64-osx
CMake์์ vcpkg ์ฌ์ฉ:
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake
# ๋๋ ํ๊ฒฝ๋ณ์ ์ค์
export CMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
โ ๏ธ ์์กด์ฑ ๊ด๋ฆฌ ๋ฒ ์คํธ ํ๋ํฐ์ค
1. ๋ฒ์ ๊ณ ์ : ์์กด์ฑ ๋ฒ์ ์ ๋ช
ํํ ์ง์ ํด์ ์ฌํ ๊ฐ๋ฅํ ๋น๋ ๋ณด์ฅ
2. ์ต์ํ: ์ ๋ง ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ง ์ฌ์ฉ (๋น๋ ์๊ฐ๊ณผ ๋ฐ์ด๋๋ฆฌ ํฌ๊ธฐ ๊ณ ๋ ค)
3. ๋ผ์ด์ ์ค ํ์ธ: ์์ฉ ํ๋ก์ ํธ๋ผ๋ฉด ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ผ์ด์ ์ค ๊ผญ ์ฒดํฌ
4. ๋ณด์ ์
๋ฐ์ดํธ: ์ ๊ธฐ์ ์ผ๋ก ์์กด์ฑ ์
๋ฐ์ดํธํด์ ๋ณด์ ์ทจ์ฝ์ ํจ์น
๐งช ํฌ๋ก์ค ํ๋ซํผ ํ ์คํ ์ ๋ต
์ฝ๋๋ฅผ ์ฌ๋ฌ ํ๋ซํผ์์ ๋น๋ํ๋ค๊ณ ๋์ด ์๋์ผ. ๊ฐ ํ๋ซํผ์์ ์ ๋๋ก ๋์ํ๋์ง ํ ์คํธํ๋ ๊ฒ ์ ๋ง ์ค์ํด! ๐ฌ
๐ฏ ์๋ํ๋ ํ ์คํธ ํ๊ฒฝ ๊ตฌ์ถ
1. ๋จ์ ํ ์คํธ (Unit Testing)
Google Test๋ Catch2 ๊ฐ์ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋ซํผ ๋ ๋ฆฝ์ ์ธ ํ ์คํธ๋ฅผ ์์ฑํ ์ ์์ด.
// CMakeLists.txt์ ํ
์คํธ ์ถ๊ฐ
enable_testing()
# Google Test ์ถ๊ฐ
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
FetchContent_MakeAvailable(googletest)
# ํ
์คํธ ์คํ ํ์ผ
add_executable(unit_tests
tests/test_core.cpp
tests/test_utils.cpp
)
target_link_libraries(unit_tests
gtest_main
myproject_lib
)
add_test(NAME UnitTests COMMAND unit_tests)
ํ๋ซํผ๋ณ ํ ์คํธ ์ผ์ด์ค:
#include <gtest/gtest.h>
#include "platform_detection.h"
TEST(PlatformTest, FileSystemOperations) {
// ํ๋ซํผ ๋
๋ฆฝ์ ํ
์คํธ
auto path = std::filesystem::temp_directory_path();
EXPECT_TRUE(std::filesystem::exists(path));
}
#ifdef PLATFORM_WINDOWS
TEST(WindowsTest, RegistryAccess) {
// Windows ์ ์ฉ ํ
์คํธ
// ๋ ์ง์คํธ๋ฆฌ ์ ๊ทผ ํ
์คํธ
}
#endif
#ifdef PLATFORM_LINUX
TEST(LinuxTest, ProcFileSystem) {
// Linux ์ ์ฉ ํ
์คํธ
EXPECT_TRUE(std::filesystem::exists("/proc/cpuinfo"));
}
#endif
2. CI/CD ํ์ดํ๋ผ์ธ ๊ตฌ์ถ
GitHub Actions, GitLab CI, Jenkins ๋ฑ์ ํ์ฉํ๋ฉด ์ฌ๋ฌ ํ๋ซํผ์์ ์๋์ผ๋ก ๋น๋ํ๊ณ ํ ์คํธํ ์ ์์ด.
# .github/workflows/build.yml
name: Multi-Platform Build
on: [push, pull_request]
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: sudo apt-get install -y cmake g++
- name: Build
run: |
mkdir build && cd build
cmake ..
make -j$(nproc)
- name: Test
run: cd build && ctest --output-on-failure
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: |
mkdir build
cd build
cmake ..
cmake --build . --config Release
- name: Test
run: cd build && ctest -C Release --output-on-failure
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: |
mkdir build && cd build
cmake ..
make -j$(sysctl -n hw.ncpu)
- name: Test
run: cd build && ctest --output-on-failure
build-cross-arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install ARM toolchain
run: sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
- name: Cross compile
run: |
mkdir build-arm && cd build-arm
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux.cmake ..
make -j$(nproc)
๐ก ์ค์ ํ๋์จ์ด ํ ์คํธ์ ์ค์์ฑ
์๋ฎฌ๋ ์ดํฐ๋ ๊ฐ์ ํ๊ฒฝ์์์ ํ ์คํธ๋ ์ค์ํ์ง๋ง, ์ค์ ํ๊ฒ ํ๋์จ์ด์์ ํ ์คํธํ๋ ๊ฒ๋ ๊ผญ ํ์ํด! ํนํ ์๋ฒ ๋๋ ์์คํ ์ด๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์ ๊ฒฝ์ฐ, ์ฑ๋ฅ์ด๋ ํ๋์จ์ด ํน์ฑ์ด ํฌ๊ฒ ๋ค๋ฅผ ์ ์๊ฑฐ๋ . ๊ฐ๋ฅํ๋ฉด ๊ฐ ํ๋ซํผ์ ์ค์ ๊ธฐ๊ธฐ๋ฅผ ํ๋ณดํด์ ์ต์ข ํ ์คํธ๋ฅผ ์งํํ๋ ๊ฒ ์ข์. ๐ฏ
๐ ์ฑ๋ฅ ์ต์ ํ์ ํ๋ซํผ๋ณ ํ๋
๊ฐ์ ์ฝ๋๋ผ๋ ํ๋ซํผ๋ง๋ค ์ฑ๋ฅ์ด ๋ค๋ฅผ ์ ์์ด. ๊ฐ ํ๋ซํผ์ ํน์ฑ์ ์ดํดํ๊ณ ์ต์ ํํ๋ฉด ํจ์ฌ ๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ง! โก
๐ฏ ์ปดํ์ผ๋ฌ ์ต์ ํ ์ต์
๊ฐ ์ปดํ์ผ๋ฌ๋ง๋ค ์ต์ ํ ์ต์ ์ด ์กฐ๊ธ์ฉ ๋ฌ๋ผ. ํ๋ซํผ๋ณ๋ก ์ ์ ํ ์ต์ ์ ์ค์ ํด์ฃผ๋ ๊ฒ ์ค์ํด.
# CMake์์ ํ๋ซํผ๋ณ ์ต์ ํ ์ค์
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# GCC/Clang ์ต์ ํ
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -mtune=native -flto")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math")
# ARM ํนํ ์ต์ ํ
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -mfloat-abi=hard")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
# MSVC ์ต์ ํ
set(CMAKE_CXX_FLAGS_RELEASE "/O2 /GL /arch:AVX2")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG")
endif()
# ๋๋ฒ๊ทธ ๋น๋ ์ต์ ํ (๋๋ฒ๊น
๊ฐ๋ฅํ๋ฉด์๋ ์ ๋นํ ์๋)
set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g")
๐ฅ GCC/Clang ์ต์ ํ ๋ ๋ฒจ
-O0: ์ต์ ํ ์์ (๋๋ฒ๊น
์ฉ)
-O1: ๊ธฐ๋ณธ ์ต์ ํ
-O2: ๊ถ์ฅ ์ต์ ํ (๋๋ถ๋ถ ์ฌ์ฉ)
-O3: ๊ณต๊ฒฉ์ ์ต์ ํ
-Os: ํฌ๊ธฐ ์ต์ ํ
-Ofast: ์ต๋ ์๋ (ํ์ค ์๋ฐ ๊ฐ๋ฅ)
โก MSVC ์ต์ ํ ์ต์
/Od: ์ต์ ํ ๋นํ์ฑํ
/O1: ํฌ๊ธฐ ์ต์ํ
/O2: ์๋ ์ต๋ํ (๊ถ์ฅ)
/Ox: ์ ์ฒด ์ต์ ํ
/GL: ์ ์ฒด ํ๋ก๊ทธ๋จ ์ต์ ํ
/arch:AVX2: SIMD ๋ช
๋ น์ด ์ฌ์ฉ
๐ ํ๋กํ์ผ๋ง๊ณผ ๋ณ๋ชฉ ์ง์ ์ฐพ๊ธฐ
์ต์ ํ์ ์ฒซ ๋จ๊ณ๋ ์ธก์ ์ด์ผ. ์ด๋๊ฐ ๋๋ฆฐ์ง ์์์ผ ๊ฐ์ ํ ์ ์์ผ๋๊น!
ํ๋ซํผ๋ณ ํ๋กํ์ผ๋ง ๋๊ตฌ:
| ํ๋ซํผ | ํ๋กํ์ผ๋ฌ | ํน์ง |
|---|---|---|
| Linux | perf, Valgrind, gprof | ๋ฌด๋ฃ, ๊ฐ๋ ฅํ ๋ถ์ ๊ธฐ๋ฅ |
| Windows | Visual Studio Profiler, Intel VTune | GUI ๊ธฐ๋ฐ, ์ง๊ด์ |
| macOS | Instruments, Xcode Profiler | ํตํฉ ๊ฐ๋ฐ ํ๊ฒฝ |
| ํฌ๋ก์ค ํ๋ซํผ | Tracy, Optick | ์ค์๊ฐ ํ๋กํ์ผ๋ง |
๊ฐ๋จํ ํ๋กํ์ผ๋ง ์ฝ๋ ์์ :
#include <chrono>
#include <iostream>
class Timer {
std::chrono::high_resolution_clock::time_point start;
const char* name;
public:
Timer(const char* n) : name(n) {
start = std::chrono::high_resolution_clock::now();
}
~Timer() {
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << name << ": " << duration.count() << " ฮผs\n";
}
};
void criticalFunction() {
Timer t("criticalFunction");
// ์ธก์ ํ ์ฝ๋
for(int i = 0; i < 1000000; ++i) {
// ์์
์ํ
}
}
๐พ ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ๊ณผ ์บ์ ์ต์ ํ
ํ๋ซํผ๋ง๋ค ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ ์๊ตฌ์ฌํญ์ด ๋ค๋ฅผ ์ ์์ด. ํนํ ARM ๊ฐ์ ์ํคํ ์ฒ์์๋ ์ ๋ ฌ๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ์ฑ๋ฅ ์ ํ๋ ํฌ๋์๋ฅผ ์ผ์ผํฌ ์ ์์ด.
// ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ ์ง์
struct alignas(16) AlignedData {
float x, y, z, w;
};
// ์บ์ ๋ผ์ธ ํฌ๊ธฐ ๊ณ ๋ ค (๋ณดํต 64๋ฐ์ดํธ)
struct alignas(64) CacheAligned {
int data[16];
};
// ์ปดํ์ผ๋ฌ๋ณ ์ ๋ ฌ ์์ฑ
#ifdef _MSC_VER
#define ALIGN(n) __declspec(align(n))
#else
#define ALIGN(n) __attribute__((aligned(n)))
#endif
ALIGN(32) float simd_data[8];
SIMD ์ต์ ํ:
ํ๋ซํผ๋ณ SIMD ๋ช ๋ น์ด๋ฅผ ํ์ฉํ๋ฉด ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ด.
#include <immintrin.h> // Intel SSE/AVX
void vectorAdd(float* a, float* b, float* result, size_t size) {
#if defined(__AVX__)
// AVX ์ฌ์ฉ ๊ฐ๋ฅ (8๊ฐ float ๋์ ์ฒ๋ฆฌ)
for(size_t i = 0; i < size; i += 8) {
__m256 va = _mm256_load_ps(&a[i]);
__m256 vb = _mm256_load_ps(&b[i]);
__m256 vr = _mm256_add_ps(va, vb);
_mm256_store_ps(&result[i], vr);
}
#elif defined(__ARM_NEON)
// ARM NEON ์ฌ์ฉ (4๊ฐ float ๋์ ์ฒ๋ฆฌ)
for(size_t i = 0; i < size; i += 4) {
float32x4_t va = vld1q_f32(&a[i]);
float32x4_t vb = vld1q_f32(&b[i]);
float32x4_t vr = vaddq_f32(va, vb);
vst1q_f32(&result[i], vr);
}
#else
// ์ผ๋ฐ ์ค์นผ๋ผ ์ฐ์ฐ
for(size_t i = 0; i < size; ++i) {
result[i] = a[i] + b[i];
}
#endif
}
๐ฑ ๋ชจ๋ฐ์ผ ๋ฐ ์๋ฒ ๋๋ ํ๋ซํผ ํฌ๋ก์ค ์ปดํ์ผ
์ด์ ์ข ๋ ํน์ํ ์ผ์ด์ค๋ฅผ ์ดํด๋ณด์. ๋ชจ๋ฐ์ผ์ด๋ ์๋ฒ ๋๋ ์์คํ ์ ๋ฐ์คํฌํฑ๊ณผ๋ ๋ค๋ฅธ ์ ๊ทผ์ด ํ์ํด! ๐ฒ
๐ค Android NDK ํฌ๋ก์ค ์ปดํ์ผ
Android ์ฑ์์ C++ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด NDK(Native Development Kit)๊ฐ ํ์ํด.
1. NDK ์ค์น ๋ฐ ํ๊ฒฝ ์ค์
# Android Studio๋ฅผ ํตํด NDK ์ค์นํ๊ฑฐ๋
# ์ง์ ๋ค์ด๋ก๋: https://developer.android.com/ndk/downloads
# ํ๊ฒฝ ๋ณ์ ์ค์
export ANDROID_NDK_HOME=/path/to/android-ndk
export PATH=$PATH:$ANDROID_NDK_HOME
2. CMake ํด์ฒด์ธ ํ์ผ ์ฌ์ฉ
# android-toolchain.cmake (NDK์ ํฌํจ๋จ)
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-24 \
-DANDROID_STL=c++_shared \
-B build-android
# ์ง์๋๋ ABI
# - armeabi-v7a (32-bit ARM)
# - arm64-v8a (64-bit ARM)
# - x86 (32-bit Intel)
# - x86_64 (64-bit Intel)
3. Gradle ํตํฉ
// app/build.gradle
android {
defaultConfig {
externalNativeBuild {
cmake {
cppFlags "-std=c++17 -frtti -fexceptions"
abiFilters 'arm64-v8a', 'armeabi-v7a'
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.22.1"
}
}
}
๐ iOS ํฌ๋ก์ค ์ปดํ์ผ
iOS ๊ฐ๋ฐ์ macOS์์๋ง ๊ฐ๋ฅํ์ง๋ง, ํฌ๋ก์ค ์ปดํ์ผ ๊ฐ๋ ์ ์ฌ์ ํ ์ ์ฉ๋ผ. ์๋ฎฌ๋ ์ดํฐ(x86_64)์ ์ค์ ๊ธฐ๊ธฐ(ARM64)๊ฐ ๋ค๋ฅธ ์ํคํ ์ฒ๋๊น!
# iOS ํด์ฒด์ธ ํ์ผ (ios.toolchain.cmake)
set(CMAKE_SYSTEM_NAME iOS)
set(CMAKE_OSX_SYSROOT iphoneos)
set(CMAKE_OSX_ARCHITECTURES arm64)
# ์๋ฎฌ๋ ์ดํฐ์ฉ
# set(CMAKE_OSX_SYSROOT iphonesimulator)
# set(CMAKE_OSX_ARCHITECTURES x86_64)
# ๋น๋
cmake -DCMAKE_TOOLCHAIN_FILE=ios.toolchain.cmake \
-GXcode \
-B build-ios
์ ๋๋ฒ์ค ํ๋ ์์ํฌ ์์ฑ:
# ๊ธฐ๊ธฐ์ฉ ๋น๋
cmake --build build-ios --config Release -- -sdk iphoneos
# ์๋ฎฌ๋ ์ดํฐ์ฉ ๋น๋
cmake --build build-ios-sim --config Release -- -sdk iphonesimulator
# XCFramework๋ก ํฉ์น๊ธฐ
xcodebuild -create-xcframework \
-framework build-ios/Release-iphoneos/MyLib.framework \
-framework build-ios-sim/Release-iphonesimulator/MyLib.framework \
-output MyLib.xcframework
๐ ์๋ฒ ๋๋ Linux (Raspberry Pi, BeagleBone ๋ฑ)
์๋ฒ ๋๋ Linux ์์คํ ์ ๋ฆฌ์์ค๊ฐ ์ ํ์ ์ด๋ผ ์ต์ ํ๊ฐ ํนํ ์ค์ํด!
# Raspberry Pi 4 (ARM Cortex-A72) ํด์ฒด์ธ
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
# Raspberry Pi ํนํ ์ต์ ํ
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=cortex-a72 -mfpu=neon-fp-armv8")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ffast-math")
# ์ ์ ๋งํฌ (์์กด์ฑ ์ต์ํ)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
ํฌ๊ธฐ ์ต์ ํ (์๋ฒ ๋๋ ์์คํ ์์ ์ค์!):
# ๋ถํ์ํ ์ฌ๋ณผ ์ ๊ฑฐ
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
# ๋งํฌ ํ์ ์ต์ ํ
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
# ์ฌ์ฉํ์ง ์๋ ํจ์ ์ ๊ฑฐ
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
# ๊ฒฐ๊ณผ ํ์ธ
# arm-linux-gnueabihf-size myapp
# arm-linux-gnueabihf-strip myapp # ์ถ๊ฐ ํฌ๊ธฐ ๊ฐ์
โ ๏ธ ์๋ฒ ๋๋ ๊ฐ๋ฐ ์ ์ฃผ์์ฌํญ
1. ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ: ๋์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์ต์ํ, ์คํ ํฌ๊ธฐ ๊ณ ๋ ค
2. ์ ๋ ฅ ์๋น: ๋ถํ์ํ ์ฐ์ฐ ์ค์ด๊ธฐ, ์ฌ๋ฆฝ ๋ชจ๋ ํ์ฉ
3. ์ค์๊ฐ์ฑ: ์๊ฐ ์ ์ฝ์ด ์๋ค๋ฉด RTOS ๊ณ ๋ ค
4. ํ๋์จ์ด ์ ๊ทผ: ๋ฉ๋ชจ๋ฆฌ ๋งต I/O, ์ธํฐ๋ฝํธ ์ฒ๋ฆฌ ํ์
5. ๋๋ฒ๊น
: ์๊ฒฉ ๋๋ฒ๊น
ํ๊ฒฝ ๊ตฌ์ถ (GDB server ๋ฑ)
๐ ๋ณด์ ๊ณ ๋ ค์ฌํญ
ํฌ๋ก์ค ํ๋ซํผ ๊ฐ๋ฐ์์ ๋ณด์๋ ์ ๋ง ์ค์ํด. ํ๋ซํผ๋ง๋ค ๋ณด์ ๋ฉ์ปค๋์ฆ์ด ๋ค๋ฅด๋๊น ๊ฐ๊ฐ์ ๋ง๊ฒ ๋์ํด์ผ ํด! ๐ก๏ธ
๐ ํ๋ซํผ๋ณ ๋ณด์ ๊ธฐ๋ฅ
1. ์ฝ๋ ์๋ช (Code Signing)
// Windows: Authenticode
signtool sign /f certificate.pfx /p password /t http://timestamp.server.com myapp.exe
// macOS: codesign
codesign --force --deep --sign "Developer ID Application: Your Name" MyApp.app
// Linux: AppImage ์๋ช
gpg --detach-sign MyApp.AppImage
2. ๋ฉ๋ชจ๋ฆฌ ๋ณดํธ ๊ธฐ๋ฒ
// CMake์์ ๋ณด์ ํ๋๊ทธ ํ์ฑํ
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Stack canary (์คํ ์ค๋ฒํ๋ก์ฐ ๊ฐ์ง)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong")
# Position Independent Executable
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# RELRO (Relocation Read-Only)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now")
# NX bit (์คํ ๋ฐฉ์ง)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,noexecstack")
endif()
if(MSVC)
# Control Flow Guard
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /guard:cf")
# Data Execution Prevention
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NXCOMPAT")
# Address Space Layout Randomization
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DYNAMICBASE")
endif()
3. ์์ ํ ๋ฌธ์์ด ์ฒ๋ฆฌ
#include <string_view>
#include <span>
// ๋ฒํผ ์ค๋ฒํ๋ก์ฐ ๋ฐฉ์ง
void safeStringCopy(char* dest, size_t destSize, const char* src) {
#ifdef _MSC_VER
strcpy_s(dest, destSize, src);
#else
strncpy(dest, src, destSize - 1);
dest[destSize - 1] = '\0';
#endif
}
// ํ๋์ C++ ๋ฐฉ์ (๋ ์์ )
void processData(std::string_view data) {
// string_view๋ ๋ณต์ฌ ์์ด ์์ ํ๊ฒ ๋ฌธ์์ด ์ฐธ์กฐ
}
void processBuffer(std::span<const uint8_t> buffer) {
// span์ ๊ฒฝ๊ณ ๊ฒ์ฌ๋ฅผ ์ ๊ณต
if(buffer.size() < 10) return;
// ์์ ํ ์ ๊ทผ
}
๐จ ์ค์ ํ๋ก์ ํธ: ํฌ๋ก์ค ํ๋ซํผ ํ์ผ ์ํธํ ๋๊ตฌ
์ด๋ก ๋ง ๋ฐฐ์ฐ๋ฉด ์ฌ๋ฏธ์์ผ๋, ์ค์ ๋ก ๋์ํ๋ ํฌ๋ก์ค ํ๋ซํผ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณด์! ๊ฐ๋จํ ํ์ผ ์ํธํ ๋๊ตฌ๋ฅผ ์์ ๋ก ์ดํด๋ณผ๊ฒ. ๐
๐ ํ๋ก์ ํธ ๊ตฌ์กฐ
FileCryptor/
โโโ CMakeLists.txt
โโโ src/
โ โโโ main.cpp
โ โโโ crypto/
โ โ โโโ aes.cpp
โ โ โโโ aes.h
โ โโโ platform/
โ โโโ file_io.h
โ โโโ windows_file.cpp
โ โโโ posix_file.cpp
โ โโโ platform_utils.h
โโโ toolchains/
โ โโโ linux-arm.cmake
โ โโโ mingw-w64.cmake
โ โโโ android.cmake
โโโ tests/
โโโ crypto_tests.cpp
๐ป ํต์ฌ ์ฝ๋ ๊ตฌํ
1. ํ๋ซํผ ์ถ์ํ ์ธํฐํ์ด์ค
// platform/file_io.h
#pragma once
#include <string>
#include <vector>
#include <memory>
class IFileIO {
public:
virtual ~IFileIO() = default;
virtual bool readFile(const std::string& path, std::vector<uint8_t>& data) = 0;
virtual bool writeFile(const std::string& path, const std::vector<uint8_t>& data) = 0;
virtual bool fileExists(const std::string& path) = 0;
virtual uint64_t getFileSize(const std::string& path) = 0;
};
std::unique_ptr<IFileIO> createFileIO();
2. Windows ๊ตฌํ
// platform/windows_file.cpp
#ifdef _WIN32
#include "file_io.h"
#include <windows.h>
#include <fstream>
class WindowsFileIO : public IFileIO {
public:
bool readFile(const std::string& path, std::vector<uint8_t>& data) override {
std::ifstream file(path, std::ios::binary | std::ios::ate);
if(!file) return false;
auto size = file.tellg();
data.resize(size);
file.seekg(0);
file.read(reinterpret_cast<char*>(data.data()), size);
return file.good();
}
bool writeFile(const std::string& path, const std::vector<uint8_t>& data) override {
std::ofstream file(path, std::ios::binary);
if(!file) return false;
file.write(reinterpret_cast<const char*>(data.data()), data.size());
return file.good();
}
bool fileExists(const std::string& path) override {
DWORD attr = GetFileAttributesA(path.c_str());
return (attr != INVALID_FILE_ATTRIBUTES);
}
uint64_t getFileSize(const std::string& path) override {
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
if(!GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &fileInfo))
return 0;
LARGE_INTEGER size;
size.HighPart = fileInfo.nFileSizeHigh;
size.LowPart = fileInfo.nFileSizeLow;
return size.QuadPart;
}
};
std::unique_ptr<IFileIO> createFileIO() {
return std::make_unique<WindowsFileIO>();
}
#endif
3. POSIX (Linux/macOS) ๊ตฌํ
// platform/posix_file.cpp
#if defined(__linux__) || defined(__APPLE__)
#include "file_io.h"
#include <sys/stat.h>
#include <fstream>
class PosixFileIO : public IFileIO {
public:
bool readFile(const std::string& path, std::vector<uint8_t>& data) override {
std::ifstream file(path, std::ios::binary | std::ios::ate);
if(!file) return false;
auto size = file.tellg();
data.resize(size);
file.seekg(0);
file.read(reinterpret_cast<char*>(data.data()), size);
return file.good();
}
bool writeFile(const std::string& path, const std::vector<uint8_t>& data) override {
std::ofstream file(path, std::ios::binary);
if(!file) return false;
file.write(reinterpret_cast<const char*>(data.data()), data.size());
return file.good();
}
bool fileExists(const std::string& path) override {
struct stat buffer;
return (stat(path.c_str(), &buffer) == 0);
}
uint64_t getFileSize(const std::string& path) override {
struct stat st;
if(stat(path.c_str(), &st) != 0)
return 0;
return st.st_size;
}
};
std::unique_ptr<IFileIO> createFileIO() {
return std::make_unique<PosixFileIO>();
}
#endif
4. ๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์
// main.cpp
#include <iostream>
#include <string>
#include "platform/file_io.h"
#include "crypto/aes.h"
int main(int argc, char* argv[]) {
if(argc < 4) {
std::cout << "Usage: filecryptor [encrypt|decrypt] input output\n";
return 1;
}
std::string mode = argv[1];
std::string inputPath = argv[2];
std::string outputPath = argv[3];
auto fileIO = createFileIO();
// ํ์ผ ์ฝ๊ธฐ
std::vector<uint8_t> data;
if(!fileIO->readFile(inputPath, data)) {
std::cerr << "Failed to read file: " << inputPath << "\n";
return 1;
}
std::cout << "Read " << data.size() << " bytes from " << inputPath << "\n";
// ์ํธํ/๋ณตํธํ
std::vector<uint8_t> result;
if(mode == "encrypt") {
result = AES::encrypt(data, "my-secret-key");
std::cout << "Encrypted successfully\n";
} else if(mode == "decrypt") {
result = AES::decrypt(data, "my-secret-key");
std::cout << "Decrypted successfully\n";
} else {
std::cerr << "Invalid mode: " << mode << "\n";
return 1;
}
// ํ์ผ ์ฐ๊ธฐ
if(!fileIO->writeFile(outputPath, result)) {
std::cerr << "Failed to write file: " << outputPath << "\n";
return 1;
}
std::cout << "Wrote " << result.size() << " bytes to " << outputPath << "\n";
return 0;
}
5. CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(FileCryptor VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ์์ค ํ์ผ
set(COMMON_SOURCES
src/main.cpp
src/crypto/aes.cpp
)
# ํ๋ซํผ๋ณ ์์ค
if(WIN32)
list(APPEND PLATFORM_SOURCES src/platform/windows_file.cpp)
elseif(UNIX)
list(APPEND PLATFORM_SOURCES src/platform/posix_file.cpp)
endif()
add_executable(filecryptor ${COMMON_SOURCES} ${PLATFORM_SOURCES})
target_include_directories(filecryptor PRIVATE src)
# ํ๋ซํผ๋ณ ๋งํฌ
if(WIN32)
# Windows ํน๋ณํ ๋งํฌ ์์
elseif(APPLE)
# macOS ํ๋ ์์ํฌ
target_link_libraries(filecryptor "-framework CoreFoundation")
elseif(UNIX)
# Linux pthread
target_link_libraries(filecryptor pthread)
endif()
# ์ค์น ๊ท์น
install(TARGETS filecryptor DESTINATION bin)
๐ ๋น๋ ๋ฐ ํ ์คํธ
# Linux ๋น๋
mkdir build && cd build
cmake ..
make
./filecryptor encrypt test.txt test.enc
./filecryptor decrypt test.enc test_decrypted.txt
# Windows ํฌ๋ก์ค ์ปดํ์ผ (Linux์์)
mkdir build-windows && cd build-windows
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/mingw-w64.cmake ..
make
# ARM Linux ํฌ๋ก์ค ์ปดํ์ผ
mkdir build-arm && cd build-arm
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/linux-arm.cmake ..
make
๐ ์ปจํ ์ด๋ ๊ธฐ๋ฐ ํฌ๋ก์ค ์ปดํ์ผ
์ต๊ทผ์๋ Docker๋ฅผ ํ์ฉํ ํฌ๋ก์ค ์ปดํ์ผ์ด ์ ๋ง ์ธ๊ธฐ์ผ! ํ๊ฒฝ ์ค์ ์ด ๊ฐํธํ๊ณ , ์ฌํ ๊ฐ๋ฅํ ๋น๋๋ฅผ ๋ณด์ฅํ๊ฑฐ๋ . ๐ณ
๐ณ Docker๋ฅผ ํ์ฉํ ๋ฉํฐ ํ๋ซํผ ๋น๋
1. ๋ฉํฐ ์คํ ์ด์ง Dockerfile
# Dockerfile.multiplatform
FROM ubuntu:22.04 AS base
RUN apt-get update && apt-get install -y \
cmake \
ninja-build \
git \
&& rm -rf /var/lib/apt/lists/*
# Linux x86_64 ๋น๋
FROM base AS build-linux-x64
RUN apt-get update && apt-get install -y g++
WORKDIR /app
COPY . .
RUN cmake -B build -G Ninja && cmake --build build
RUN cp build/filecryptor /output/filecryptor-linux-x64
# Linux ARM ํฌ๋ก์ค ์ปดํ์ผ
FROM base AS build-linux-arm
RUN apt-get update && apt-get install -y \
gcc-arm-linux-gnueabihf \
g++-arm-linux-gnueabihf
WORKDIR /app
COPY . .
COPY toolchains/linux-arm.cmake .
RUN cmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=linux-arm.cmake \
&& cmake --build build
RUN cp build/filecryptor /output/filecryptor-linux-arm
# Windows ํฌ๋ก์ค ์ปดํ์ผ
FROM base AS build-windows
RUN apt-get update && apt-get install -y mingw-w64
WORKDIR /app
COPY . .
COPY toolchains/mingw-w64.cmake .
RUN cmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=mingw-w64.cmake \
&& cmake --build build
RUN cp build/filecryptor.exe /output/filecryptor-windows.exe
# ์ต์ข
์ด๋ฏธ์ง (๋ชจ๋ ๋น๋ ๊ฒฐ๊ณผ ์์ง)
FROM scratch AS export
COPY --from=build-linux-x64 /output/* /
COPY --from=build-linux-arm /output/* /
COPY --from=build-windows /output/* /
2. Docker Buildx๋ก ๋ฉํฐ ์ํคํ ์ฒ ๋น๋
# buildx ์ค์
docker buildx create --name multiplatform --use
docker buildx inspect --bootstrap
# ๋ฉํฐ ํ๋ซํผ ๋น๋ ๋ฐ ์ถ์ถ
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
--target export \
--output type=local,dest=./dist \
-f Dockerfile.multiplatform .
# ๊ฒฐ๊ณผ ํ์ธ
ls -lh dist/
# filecryptor-linux-x64
# filecryptor-linux-arm
# filecryptor-windows.exe
3. Docker Compose๋ก ๋น๋ ์๋ํ
# docker-compose.yml
version: '3.8'
services:
build-linux:
image: gcc:12
volumes:
- .:/workspace
working_dir: /workspace
command: >
bash -c "
mkdir -p build-linux &&
cd build-linux &&
cmake .. &&
make -j$(nproc)
"
build-windows:
image: ubuntu:22.04
volumes:
- .:/workspace
working_dir: /workspace
command: >
bash -c "
apt-get update &&
apt-get install -y cmake mingw-w64 &&
mkdir -p build-windows &&
cd build-windows &&
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/mingw-w64.cmake .. &&
make -j$(nproc)
"
build-arm:
image: ubuntu:22.04
volumes:
- .:/workspace
working_dir: /workspace
command: >
bash -c "
apt-get update &&
apt-get install -y cmake gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf &&
mkdir -p build-arm &&
cd build-arm &&
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/linux-arm.cmake .. &&
make -j$(nproc)
"
# ์คํ
# docker-compose up
๐ก ์ปจํ ์ด๋ ๊ธฐ๋ฐ ๋น๋์ ์ฅ์
โ
ํ๊ฒฝ ์ผ๊ด์ฑ: ๋ชจ๋ ๊ฐ๋ฐ์๊ฐ ๋์ผํ ๋น๋ ํ๊ฒฝ ์ฌ์ฉ
โ
์์กด์ฑ ๊ฒฉ๋ฆฌ: ํธ์คํธ ์์คํ
์ค์ผ ์์
โ
์ฌํ ๊ฐ๋ฅ์ฑ: ์ธ์ ๋ ๋์ผํ ๊ฒฐ๊ณผ ๋ณด์ฅ
โ
CI/CD ํตํฉ: ์๋ํ ํ์ดํ๋ผ์ธ์ ์ฝ๊ฒ ํตํฉ
โ
๋ฒ์ ๊ด๋ฆฌ: Dockerfile๋ก ๋น๋ ํ๊ฒฝ ๋ฒ์ ๊ด๋ฆฌ
๐ ๊ณ ๊ธ ์ฃผ์ : ๋น๋ ์์คํ ๋น๊ต
CMake ์ธ์๋ ๋ค์ํ ๋น๋ ์์คํ ์ด ์์ด. ๊ฐ๊ฐ์ ์ฅ๋จ์ ์ ์์๋๋ฉด ํ๋ก์ ํธ์ ๋ง๋ ์ ํ์ ํ ์ ์์ง! ๐
| ๋น๋ ์์คํ | ์ฅ์ | ๋จ์ | ์ ํฉํ ๊ฒฝ์ฐ |
|---|---|---|---|
| CMake | ํฌ๋ก์ค ํ๋ซํผ, ๋๋ฆฌ ์ฌ์ฉ๋จ, IDE ํตํฉ ์ฐ์ | ๋ฌธ๋ฒ์ด ๋ค์ ๋ณต์ก, ํ์ต ๊ณก์ | ๋๋ถ๋ถ์ C++ ํ๋ก์ ํธ |
| Meson | ๋น ๋ฅธ ๋น๋ ์๋, ๊ฐ๊ฒฐํ ๋ฌธ๋ฒ | ์๋์ ์ผ๋ก ์ ์ ์ฌ์ฉ์ ๊ธฐ๋ฐ | ์ ํ๋ก์ ํธ, ๋น ๋ฅธ ๋น๋ ํ์ |
| Bazel | ๋๊ท๋ชจ ํ๋ก์ ํธ, ์ฆ๋ถ ๋น๋ ์ต์ ํ | ๋ณต์กํ ์ค์ , ๊ฐํ๋ฅธ ํ์ต ๊ณก์ | Google ์คํ์ผ ๋๊ท๋ชจ ํ๋ก์ ํธ |
| Premake | Lua ๊ธฐ๋ฐ, ๊ฐ๋จํ ์คํฌ๋ฆฝํ | ๊ธฐ๋ฅ์ด ์ ํ์ | ๊ฒ์ ๊ฐ๋ฐ, ์ค์ ๊ท๋ชจ ํ๋ก์ ํธ |
| xmake | ํ๋์ , Lua ๊ธฐ๋ฐ, ํจํค์ง ๊ด๋ฆฌ ๋ด์ฅ | ๋น๊ต์ ์๋ก์ด ๋๊ตฌ | ์ค๊ตญ ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ, ์ ๊ท ํ๋ก์ ํธ |
๐น Meson ์์
# meson.build
project('filecryptor', 'cpp',
version : '1.0.0',
default_options : ['cpp_std=c++17'])
sources = [
'src/main.cpp',
'src/crypto/aes.cpp',
]
# ํ๋ซํผ๋ณ ์์ค ์ถ๊ฐ
if host_machine.system() == 'windows'
sources += 'src/platform/windows_file.cpp'
elif host_machine.system() in ['linux', 'darwin']
sources += 'src/platform/posix_file.cpp'
endif
executable('filecryptor',
sources,
install : true)
# ํฌ๋ก์ค ์ปดํ์ผ ํ์ผ (cross-arm.txt)
[binaries]
c = 'arm-linux-gnueabihf-gcc'
cpp = 'arm-linux-gnueabihf-g++'
ar = 'arm-linux-gnueabihf-ar'
strip = 'arm-linux-gnueabihf-strip'
[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'
# ๋น๋
# meson setup build --cross-file cross-arm.txt
# meson compile -C build
๐น Bazel ์์
# BUILD
cc_binary(
name = "filecryptor",
srcs = [
"src/main.cpp",
"src/crypto/aes.cpp",
] + select({
"@platforms//os:windows": ["src/platform/windows_file.cpp"],
"@platforms//os:linux": ["src/platform/posix_file.cpp"],
"@platforms//os:macos": ["src/platform/posix_file.cpp"],
}),
hdrs = [
"src/crypto/aes.h",
"src/platform/file_io.h",
],
copts = ["-std=c++17"],
)
# ํฌ๋ก์ค ์ปดํ์ผ
# bazel build --platforms=@io_bazel_rules_go//go/toolchain:linux_arm64 //:filecryptor
๐จ ํํ ๋ฌธ์ ์ ํด๊ฒฐ ๋ฐฉ๋ฒ
ํฌ๋ก์ค ์ปดํ์ผํ๋ค ๋ณด๋ฉด ์ฌ๋ฌ ๊ฐ์ง ๋ฌธ์ ์ ๋ถ๋ชํ๊ฒ ๋ผ. ์์ฃผ ๋ฐ์ํ๋ ๋ฌธ์ ๋ค๊ณผ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด๋ดค์ด! ๐ง
โ ๋ฌธ์ 1: "Cannot find -lstdc++" ์๋ฌ
์์ธ: ํฌ๋ก์ค ์ปดํ์ผ ํด์ฒด์ธ์ C++ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์
ํด๊ฒฐ:
# ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
sudo apt-get install libstdc++-11-dev-armhf-cross
# ๋๋ ์ ์ ๋งํฌ
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
โ ๋ฌธ์ 2: ์คํ ์ "cannot execute binary file"
์์ธ: ์๋ชป๋ ์ํคํ ์ฒ๋ก ์ปดํ์ผ๋จ
ํด๊ฒฐ:
# ๋ฐ์ด๋๋ฆฌ ์ ๋ณด ํ์ธ
file myapp
# ์ถ๋ ฅ: myapp: ELF 32-bit LSB executable, ARM, ...
# ์ฌ๋ฐ๋ฅธ ํด์ฒด์ธ ์ฌ์ฉ ํ์ธ
which arm-linux-gnueabihf-g++
# CMake ์บ์ ์ญ์ ํ ์ฌ๋น๋
rm -rf build && mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake ..
โ ๋ฌธ์ 3: ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ๋ถ์ผ์น
์์ธ: ํธ์คํธ์ ํ๊ฒ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ์ด ๋ค๋ฆ
ํด๊ฒฐ:
# ์ ์ ๋งํฌ ์ฌ์ฉ
set(BUILD_SHARED_LIBS OFF)
# ๋๋ ํ๊ฒ ์์คํ
์ sysroot ์ฌ์ฉ
set(CMAKE_SYSROOT /path/to/target/sysroot)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
# ์์กด์ฑ์ ํจ๊ป ๋ฐฐํฌ
ldd myapp # ํ์ํ .so ํ์ผ ํ์ธ
# ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํจ๊ป ํจํค์ง
โ ๋ฌธ์ 4: ์๋์(Endianness) ๋ฌธ์
์์ธ: ๋น ์๋์๊ณผ ๋ฆฌํ ์๋์ ์์คํ ๊ฐ ๋ฐ์ดํฐ ๊ตํ
ํด๊ฒฐ:
#include <bit> // C++20
// ์๋์ ๋ณํ ํจ์
uint32_t swapEndian(uint32_t value) {
return ((value & 0xFF000000) >> 24) |
((value & 0x00FF0000) >> 8) |
((value & 0x0000FF00) << 8) |
((value & 0x000000FF) << 24);
}
// ๋คํธ์ํฌ ๋ฐ์ดํธ ์์ ์ฌ์ฉ (ํญ์ ๋น
์๋์)
#include <arpa/inet.h> // POSIX
uint32_t networkValue = htonl(hostValue); // host to network
uint32_t hostValue = ntohl(networkValue); // network to host
// C++20 ๋ฐฉ์
if constexpr (std::endian::native == std::endian::big) {
// ๋น
์๋์ ์ฒ๋ฆฌ
} else {
// ๋ฆฌํ ์๋์ ์ฒ๋ฆฌ
}
โ ๋ฌธ์ 5: ํ๋ซํผ๋ณ ๋งคํฌ๋ก ์ถฉ๋
์์ธ: Windows์ min/max ๋งคํฌ๋ก ๋ฑ์ด C++ ์ฝ๋์ ์ถฉ๋
ํด๊ฒฐ:
// Windows.h ํฌํจ ์ ์
#define NOMINMAX // min/max ๋งคํฌ๋ก ๋นํ์ฑํ
#define WIN32_LEAN_AND_MEAN // ๋ถํ์ํ ํค๋ ์ ์ธ
#include <windows.h>
// ๋๋ std::min/max ๋ช
์์ ์ฌ์ฉ
int result = (std::min)(a, b); // ๊ดํธ๋ก ๋งคํฌ๋ก ํ์ฅ ๋ฐฉ์ง
// CMake์์ ์ ์ญ ์ ์
if(WIN32)
add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN)
endif()
๐ ๋๋ฒ๊น ํ
1. verbose ๋ชจ๋: `make VERBOSE=1` ๋๋ `cmake --build . --verbose`๋ก ์์ธ ๋ก๊ทธ ํ์ธ
2. ํด์ฒด์ธ ๊ฒ์ฆ: ๊ฐ๋จํ "Hello World" ํ๋ก๊ทธ๋จ์ผ๋ก ๋จผ์ ํ
์คํธ
3. QEMU ํ์ฉ: ํฌ๋ก์ค ์ปดํ์ผ๋ ๋ฐ์ด๋๋ฆฌ๋ฅผ ํธ์คํธ์์ ์คํํด๋ณด๊ธฐ
4. ์๊ฒฉ ๋๋ฒ๊น
: gdbserver๋ฅผ ํ๊ฒ์์ ์คํํ๊ณ ํธ์คํธ์์ ์ฐ๊ฒฐ
5. ๋ก๊ทธ ์ถ๊ฐ: ํ๋ซํผ๋ณ ์ฝ๋ ๊ฒฝ๋ก์ ๋ก๊ทธ๋ฅผ ์ถ๊ฐํด์ ์คํ ํ๋ฆ ํ์ธ
๐ ์ถ๊ฐ ํ์ต ๋ฆฌ์์ค
ํฌ๋ก์ค ์ปดํ์ผ๊ณผ ๋ฉํฐ ํ๋ซํผ ๊ฐ๋ฐ์ ์ ๋ง ๋์ ๋ถ์ผ์ผ. ๊ณ์ ๊ณต๋ถํ๊ณ ์ถ๋ค๋ฉด ์ด๋ฐ ๋ฆฌ์์ค๋ค์ ์ฐธ๊ณ ํด๋ด! ๐
๐ ๊ณต์ ๋ฌธ์
โข CMake Documentation
โข GCC Cross-Compilation
โข LLVM Cross-Compilation Guide
โข Android NDK Documentation
โข Apple Developer Documentation
๐ ์จ๋ผ์ธ ๊ฐ์ข
โข Udemy: C++ Cross-Platform Development
โข Coursera: Build Systems
โข YouTube: CMake Tutorial Series
โข ์ฌ๋ฅ๋ท์ C++ ์ ๋ฌธ๊ฐ ๋ฉํ ๋ง
๐ ์ถ์ฒ ๋์
โข "Professional CMake"
โข "Cross-Platform Development in C++"
โข "Mastering CMake"
โข "Modern CMake for C++"
๐ ์ปค๋ฎค๋ํฐ
โข Stack Overflow (cmake, cross-compiling ํ๊ทธ)
โข Reddit r/cpp
โข CMake Discourse
โข C++ Slack ์ปค๋ฎค๋ํฐ
๐ฏ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์, ์ ๋ง ๊ธด ์ฌ์ ์ด์์ง? ๐ ํฌ๋ก์ค ์ปดํ์ผ๊ณผ ๋ฉํฐ ํ๋ซํผ ๋น๋ ํ๊ฒฝ ๊ตฌ์ฑ์ ๋ํด ์ ๋ง ๋ง์ ๊ฑธ ๋ค๋ค์ด!
๐ ํต์ฌ ์์ฝ
โ
ํฌ๋ก์ค ์ปดํ์ผ์ ํ ํ๋ซํผ์์ ๋ค๋ฅธ ํ๋ซํผ์ฉ ์คํ ํ์ผ์ ๋ง๋๋ ๊ธฐ์
โ
CMake๋ ํ๋์ ์ธ C++ ํ๋ก์ ํธ์ ์ฌ์ค์ ํ์ค ๋น๋ ์์คํ
โ
ํด์ฒด์ธ ํ์ผ๋ก ํ๊ฒ ํ๋ซํผ ์ ๋ณด๋ฅผ ์ ์
โ
ํ๋ซํผ ์ถ์ํ๋ก ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ ๊ทน๋ํ
โ
์์กด์ฑ ๊ด๋ฆฌ๋ Conan์ด๋ vcpkg ํ์ฉ
โ
CI/CD๋ก ์๋ํ๋ ๋ฉํฐ ํ๋ซํผ ๋น๋ ๊ตฌ์ถ
โ
Docker๋ก ์ผ๊ด๋ ๋น๋ ํ๊ฒฝ ๋ณด์ฅ
โ
ํ
์คํธ๋ ๊ฐ ํ๋ซํผ์์ ์ฒ ์ ํ!
ํฌ๋ก์ค ํ๋ซํผ ๊ฐ๋ฐ์ ์ฒ์์๋ ๋ณต์กํด ๋ณด์ด์ง๋ง, ํ ๋ฒ ์ ๋๋ก ํ๊ฒฝ์ ๊ตฌ์ถํด๋๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ๋ฌด๊ธฐ๊ฐ ๋ผ. ๋์ ์ฝ๋๊ฐ Windows, Linux, macOS, ๋ชจ๋ฐ์ผ, ์๋ฒ ๋๋ ๊ธฐ๊ธฐ ๋ฑ ์ด๋์๋ ๋์๊ฐ๋ค๋ ๊ฑด ์ ๋ง ๋ฉ์ง ์ผ์ด์์? ๐
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ์ง์์ ๊ณต์ ํ๋ฉด์ ๊ณ์ ์ฑ์ฅํ๋ ๊ฒ๋ ์์ง ๋ง! ํผ์ ๊ณ ๋ฏผํ์ง ๋ง๊ณ , ์ปค๋ฎค๋ํฐ์ ํ์ ํ์ฉํ๋ ๊ฑฐ์ผ. ๐ช
์ด์ ๋๋ ํฌ๋ก์ค ์ปดํ์ผ ๋ง์คํฐ๊ฐ ๋ ์ค๋น๊ฐ ๋์ด! ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด๋ฉด์ ๊ฒฝํ์ ์์๊ฐ๊ธธ ๋ฐ๋๊ฒ. ์ฒ์์๋ ์ค์๋ ํ๊ณ ๋งํ๋ ๋ถ๋ถ๋ ์๊ฒ ์ง๋ง, ๊ทธ๊ฒ ๋ค ์ฑ์ฅ์ ๊ณผ์ ์ด๋๊น ํฌ๊ธฐํ์ง ๋ง๊ณ ๊ณ์ ๋์ ํด๋ด! ๐
Happy Cross-Compiling! ๐
๊ด๋ จ ํค์๋
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.

๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.