Skip to content

Commit f15e4d5

Browse files
committed
Add CMake build system
- Supports building on Linux, macOS, and Windows (MSVC & MinGW). - Builds both static and shared libraries on Unix-like systems and MinGW. - Enforces a static-only build when using the MSVC toolchain to avoid platform-specific DLL export complexity and library name collisions. - Generates and installs a CMake package that provides modern imported alias targets for easy consumption: - `OBUParse::static` - `OBUParse::shared` (not available on MSVC) - Includes a convenient `uninstall` target. - Builds the `obudump` command-line tool.
1 parent c2156b4 commit f15e4d5

3 files changed

Lines changed: 178 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
3+
project(OBUParse VERSION 1.0.0 LANGUAGES C)
4+
5+
# --- Set Standard Output Directories ---
6+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
7+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
8+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
9+
10+
# --- Build Options ---
11+
# On MSVC, we only build static to avoid DLL export complexity and naming collisions.
12+
# On other platforms (including MinGW on Windows), we can build both.
13+
if(MSVC)
14+
option(BUILD_SHARED_LIBS "Build the shared library (disabled on MSVC)" OFF)
15+
option(BUILD_STATIC_LIBS "Build the static library" ON)
16+
set(BUILD_SHARED_LIBS OFF) # Force OFF for MSVC
17+
else()
18+
option(BUILD_SHARED_LIBS "Build the shared library" ON)
19+
option(BUILD_STATIC_LIBS "Build the static library" ON)
20+
endif()
21+
22+
if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
23+
message(FATAL_ERROR "You must choose to build at least one library type.")
24+
endif()
25+
26+
# --- Library Targets ---
27+
28+
if(BUILD_SHARED_LIBS) # This block will now be skipped on MSVC
29+
add_library(obuparse_shared SHARED obuparse.c)
30+
set_target_properties(obuparse_shared PROPERTIES
31+
OUTPUT_NAME "obuparse"
32+
VERSION ${PROJECT_VERSION}
33+
SOVERSION 1
34+
)
35+
add_library(OBUParse::shared ALIAS obuparse_shared)
36+
endif()
37+
38+
if(BUILD_STATIC_LIBS)
39+
add_library(obuparse_static STATIC obuparse.c)
40+
# The naming collision only happens with MSVC, not MinGW.
41+
if(MSVC)
42+
set_target_properties(obuparse_static PROPERTIES OUTPUT_NAME "obuparses")
43+
else()
44+
set_target_properties(obuparse_static PROPERTIES OUTPUT_NAME "obuparse")
45+
endif()
46+
add_library(OBUParse::static ALIAS obuparse_static)
47+
endif()
48+
49+
# --- Tool Target (obudump) ---
50+
add_executable(obudump
51+
tools/obudump.c
52+
tools/json.c
53+
)
54+
# Always link the tool statically. This is now guaranteed to exist on all platforms.
55+
target_link_libraries(obudump PRIVATE obuparse_static)
56+
target_include_directories(obudump PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
57+
58+
# --- Installation ---
59+
include(GNUInstallDirs)
60+
include(CMakePackageConfigHelpers)
61+
62+
# Install the public header file
63+
install(FILES obuparse.h
64+
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
65+
)
66+
67+
set(BUILT_TARGETS "")
68+
if(TARGET obuparse_static)
69+
list(APPEND BUILT_TARGETS obuparse_static)
70+
endif()
71+
if(TARGET obuparse_shared)
72+
list(APPEND BUILT_TARGETS obuparse_shared)
73+
endif()
74+
75+
# Install the library targets that were built, and the tool
76+
install(TARGETS ${BUILT_TARGETS} obudump
77+
EXPORT OBUParseTargets
78+
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
79+
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
80+
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
81+
)
82+
83+
# Generate and install the obuparse-config.cmake file
84+
# This file tells other projects where to find the targets we just installed.
85+
write_basic_package_version_file(
86+
"${CMAKE_CURRENT_BINARY_DIR}/obuparse-config-version.cmake"
87+
VERSION ${PROJECT_VERSION}
88+
COMPATIBILITY AnyNewerVersion
89+
)
90+
91+
configure_package_config_file(
92+
"obuparse-config.cmake.in"
93+
"${CMAKE_CURRENT_BINARY_DIR}/obuparse-config.cmake"
94+
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/obuparse"
95+
)
96+
97+
# Install the generated CMake package files
98+
install(
99+
FILES
100+
"${CMAKE_CURRENT_BINARY_DIR}/obuparse-config.cmake"
101+
"${CMAKE_CURRENT_BINARY_DIR}/obuparse-config-version.cmake"
102+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/obuparse"
103+
)
104+
105+
# Install the export set, which contains the actual target information
106+
install(
107+
EXPORT OBUParseTargets
108+
FILE OBUParseTargets.cmake
109+
NAMESPACE OBUParse::
110+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/obuparse"
111+
)
112+
113+
# --- Uninstall Target ---
114+
if(NOT TARGET uninstall)
115+
configure_file(
116+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
117+
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
118+
IMMEDIATE @ONLY
119+
)
120+
121+
add_custom_target(uninstall
122+
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
123+
COMMENT "Uninstalling the project..."
124+
)
125+
endif()

cmake_uninstall.cmake.in

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# cmake_uninstall.cmake.in
2+
# This script is configured by CMake and then executed to uninstall the project.
3+
# It removes only the files listed in the manifest and the project's
4+
# specific CMake package directory.
5+
6+
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
7+
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
8+
endif()
9+
10+
# --- Stage 1: Remove all files from the manifest ---
11+
message(STATUS "--- Uninstalling files ---")
12+
file(STRINGS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" installed_files)
13+
foreach(file ${installed_files})
14+
message(STATUS "Removing: \"${file}\"")
15+
if(EXISTS "${file}" OR IS_SYMLINK "${file}")
16+
file(REMOVE "${file}")
17+
else()
18+
message(STATUS "File does not exist, skipping: \"${file}\"")
19+
endif()
20+
endforeach()
21+
22+
# --- Stage 2: Remove the project's specific CMake directory ---
23+
# This path is taken directly from the install() command in CMakeLists.txt
24+
set(package_dir "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/cmake/obuparse")
25+
26+
if(EXISTS "${package_dir}")
27+
message(STATUS "--- Cleaning up package directory ---")
28+
# Check if the directory is now empty
29+
file(GLOB children LIST_DIRECTORIES false "${package_dir}/*")
30+
if(NOT children)
31+
message(STATUS "Removing empty directory: \"${package_dir}\"")
32+
execute_process(
33+
COMMAND "@CMAKE_COMMAND@" -E rm -rf "${package_dir}"
34+
RESULT_VARIABLE res
35+
)
36+
37+
if(NOT res EQUAL 0)
38+
message(WARNING "Could not remove directory: \"${package_dir}\". It may be locked by another process.")
39+
endif()
40+
else()
41+
message(STATUS "Package directory is not empty, skipping: \"${package_dir}\"")
42+
endif()
43+
endif()
44+
45+
message(STATUS "Uninstallation complete.")

obuparse-config.cmake.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# obuparse-config.cmake.in
2+
# This file is configured by CMake and installed with the library.
3+
# It helps other projects find the OBUParse targets.
4+
5+
@PACKAGE_INIT@
6+
7+
# Include the file that contains the imported target definitions.
8+
include("${CMAKE_CURRENT_LIST_DIR}/OBUParseTargets.cmake")

0 commit comments

Comments
 (0)