Skip to content

Commit f8b00f3

Browse files
committed
Add CMake build system
- Supports building on Linux, macOS, and Windows (MSVC & MinGW). - Builds both static and shared libraries across all supported platforms. - Finds and links against a CMake-installed OBUParse dependency. (dwbuiten/obuparse#16) - Generates and installs a CMake package that provides imported alias targets for easy consumption: - `LSMASH::static` - `LSMASH::shared` - Builds the command-line tools (muxer, remuxer, boxdumper, timelineeditor) as separate executables. - Includes a convenient `uninstall` target.
1 parent fbe8653 commit f8b00f3

4 files changed

Lines changed: 290 additions & 1 deletion

File tree

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ timelineeditor
4242
*.mp3
4343
*.mp4
4444
*.qt
45-
*.txt
4645
*.vc1
4746
Debug/
4847
CLIDebug/

CMakeLists.txt

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
3+
# Extract version from lsmash.h
4+
file(STRINGS "lsmash.h" LSMASH_VERSION_MAJOR REGEX "^#define LSMASH_VERSION_MAJOR +([0-9]+)")
5+
string(REGEX REPLACE "[^0-9]" "" LSMASH_VERSION_MAJOR "${LSMASH_VERSION_MAJOR}")
6+
file(STRINGS "lsmash.h" LSMASH_VERSION_MINOR REGEX "^#define LSMASH_VERSION_MINOR +([0-9]+)")
7+
string(REGEX REPLACE "[^0-9]" "" LSMASH_VERSION_MINOR "${LSMASH_VERSION_MINOR}")
8+
file(STRINGS "lsmash.h" LSMASH_VERSION_MICRO REGEX "^#define LSMASH_VERSION_MICRO +([0-9]+)")
9+
string(REGEX REPLACE "[^0-9]" "" LSMASH_VERSION_MICRO "${LSMASH_VERSION_MICRO}")
10+
set(LSMASH_VERSION "${LSMASH_VERSION_MAJOR}.${LSMASH_VERSION_MINOR}.${LSMASH_VERSION_MICRO}")
11+
12+
project(LSMASH VERSION ${LSMASH_VERSION} LANGUAGES C)
13+
14+
# --- Build Options ---
15+
option(BUILD_SHARED_LIBS "Build the shared library" ON)
16+
option(BUILD_STATIC_LIBS "Build the static library" ON)
17+
option(LSMASH_BUILD_TOOLS "Build the command-line tools" ON)
18+
19+
if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
20+
message(FATAL_ERROR "You must build at least one library type.")
21+
endif()
22+
23+
# --- Generate config.h ---
24+
find_package(Git QUIET)
25+
if(GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
26+
execute_process(
27+
COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD
28+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
29+
OUTPUT_VARIABLE LSMASH_REV
30+
OUTPUT_STRIP_TRAILING_WHITESPACE
31+
ERROR_QUIET
32+
)
33+
execute_process(
34+
COMMAND ${GIT_EXECUTABLE} describe --always
35+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
36+
OUTPUT_VARIABLE LSMASH_GIT_HASH
37+
OUTPUT_STRIP_TRAILING_WHITESPACE
38+
ERROR_QUIET
39+
)
40+
endif()
41+
if(NOT LSMASH_REV)
42+
set(LSMASH_REV "0")
43+
endif()
44+
if(NOT LSMASH_GIT_HASH)
45+
set(LSMASH_GIT_HASH "unknown")
46+
endif()
47+
48+
configure_file(
49+
"${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
50+
"${CMAKE_CURRENT_BINARY_DIR}/config.h"
51+
)
52+
# --- Dependencies ---
53+
# L-SMASH requires obuparse. We find it here.
54+
find_package(OBUParse REQUIRED)
55+
56+
# --- Source Files ---
57+
set(SRC_COMMON
58+
common/alloc.c common/bits.c common/bytes.c
59+
common/list.c common/multibuf.c common/osdep.c common/utils.c
60+
)
61+
set(SRC_CODECS
62+
codecs/a52.c codecs/alac.c codecs/av1.c
63+
codecs/av1_obu.c codecs/description.c codecs/dts.c
64+
codecs/h264.c codecs/hevc.c codecs/id.c
65+
codecs/mp4sys.c codecs/mp4a.c codecs/mp4v.c
66+
codecs/nalu.c codecs/opus.c codecs/qt_wfex.c
67+
codecs/vc1.c codecs/wma.c
68+
)
69+
set(SRC_IMPORTER
70+
importer/a52_imp.c importer/adts_imp.c importer/als_imp.c
71+
importer/amr_imp.c importer/dts_imp.c importer/importer.c
72+
importer/isobm_imp.c importer/ivf_imp.c importer/mp3_imp.c
73+
importer/nalu_imp.c importer/vc1_imp.c importer/wave_imp.c
74+
)
75+
set(SRC_CORE
76+
core/box.c core/box_default.c core/box_type.c
77+
core/chapter.c core/file.c core/fragment.c
78+
core/isom.c core/meta.c core/print.c
79+
core/read.c core/summary.c core/timeline.c
80+
core/write.c
81+
)
82+
set(LSMASH_SOURCES
83+
${SRC_COMMON} ${SRC_CODECS} ${SRC_IMPORTER} ${SRC_CORE}
84+
)
85+
86+
# --- Library Targets ---
87+
88+
if(BUILD_SHARED_LIBS)
89+
add_library(lsmash_shared SHARED ${LSMASH_SOURCES})
90+
target_compile_definitions(lsmash_shared PRIVATE LSMASH_EXPORTS)
91+
set_target_properties(lsmash_shared PROPERTIES
92+
OUTPUT_NAME "lsmash"
93+
VERSION ${LSMASH_VERSION}
94+
SOVERSION ${LSMASH_VERSION_MAJOR}
95+
EXPORT_NAME "shared"
96+
)
97+
add_library(LSMASH::shared ALIAS lsmash_shared)
98+
endif()
99+
100+
if(BUILD_STATIC_LIBS)
101+
add_library(lsmash_static STATIC ${LSMASH_SOURCES})
102+
# On MSVC, rename the static lib to avoid collision with the shared import lib.
103+
if(MSVC)
104+
set_target_properties(lsmash_static PROPERTIES OUTPUT_NAME "lsmashs")
105+
else()
106+
set_target_properties(lsmash_static PROPERTIES OUTPUT_NAME "lsmash")
107+
endif()
108+
set_target_properties(lsmash_static PROPERTIES EXPORT_NAME "static")
109+
add_library(LSMASH::static ALIAS lsmash_static)
110+
endif()
111+
112+
# --- Common Properties for Both Library Targets ---
113+
set(BUILT_LIB_TARGETS "")
114+
if(TARGET lsmash_shared)
115+
list(APPEND BUILT_LIB_TARGETS lsmash_shared)
116+
endif()
117+
if(TARGET lsmash_static)
118+
list(APPEND BUILT_LIB_TARGETS lsmash_static)
119+
endif()
120+
121+
# Determine which OBUParse target to link against.
122+
# Prefer shared if it exists, otherwise use static. This mimics standard Unix behavior.
123+
if(TARGET OBUParse::shared)
124+
set(OBUParse_LINK_TARGET OBUParse::shared)
125+
else()
126+
set(OBUParse_LINK_TARGET OBUParse::static)
127+
endif()
128+
message(STATUS "L-SMASH will link against ${OBUParse_LINK_TARGET}")
129+
130+
foreach(target IN LISTS BUILT_LIB_TARGETS)
131+
target_include_directories(${target} PUBLIC
132+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
133+
$<INSTALL_INTERFACE:include>
134+
)
135+
# Link against the chosen OBUParse target
136+
target_link_libraries(${target} PUBLIC ${OBUParse_LINK_TARGET})
137+
if(UNIX)
138+
target_link_libraries(${target} PUBLIC m)
139+
endif()
140+
endforeach()
141+
142+
143+
# --- Tools ---
144+
set(BUILT_TOOLS_TARGETS "")
145+
if(LSMASH_BUILD_TOOLS)
146+
set(LSMASH_TOOLS_LIST muxer remuxer boxdumper timelineeditor)
147+
foreach(tool IN LISTS LSMASH_TOOLS_LIST)
148+
add_executable(${tool}
149+
cli/${tool}.c
150+
cli/cli.c
151+
)
152+
target_include_directories(${tool} PRIVATE
153+
${CMAKE_CURRENT_BINARY_DIR}
154+
)
155+
if(TARGET lsmash_shared)
156+
target_link_libraries(${tool} PRIVATE lsmash_shared)
157+
else()
158+
target_link_libraries(${tool} PRIVATE lsmash_static)
159+
endif()
160+
list(APPEND BUILT_TOOLS_TARGETS ${tool})
161+
endforeach()
162+
endif()
163+
164+
# --- RPATH Handling (Build Tree and Install Tree) ---
165+
if(UNIX AND BUILT_TOOLS_TARGETS)
166+
# This handles the build tree, allowing tools to be run from the build directory.
167+
set_property(TARGET ${BUILT_TOOLS_TARGETS} PROPERTY
168+
BUILD_RPATH "${CMAKE_BINARY_DIR}"
169+
)
170+
171+
# This handles the install tree. It sets the RPATH on the *installed* executables.
172+
set_property(TARGET ${BUILT_TOOLS_TARGETS} PROPERTY
173+
INSTALL_RPATH "\$ORIGIN/../lib"
174+
)
175+
endif()
176+
177+
# --- Installation ---
178+
include(GNUInstallDirs)
179+
include(CMakePackageConfigHelpers)
180+
181+
install(FILES lsmash.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
182+
183+
set(INSTALL_TARGETS "")
184+
if(TARGET lsmash_static)
185+
list(APPEND INSTALL_TARGETS lsmash_static)
186+
endif()
187+
if(TARGET lsmash_shared)
188+
list(APPEND INSTALL_TARGETS lsmash_shared)
189+
endif()
190+
if(BUILT_TOOLS_TARGETS)
191+
list(APPEND INSTALL_TARGETS ${BUILT_TOOLS_TARGETS})
192+
endif()
193+
194+
install(TARGETS ${INSTALL_TARGETS}
195+
EXPORT LSMASHTargets
196+
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
197+
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
198+
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
199+
)
200+
201+
# Generate and install CMake package files
202+
write_basic_package_version_file(
203+
"${CMAKE_CURRENT_BINARY_DIR}/lsmash-config-version.cmake"
204+
VERSION ${LSMASH_VERSION}
205+
COMPATIBILITY AnyNewerVersion
206+
)
207+
configure_package_config_file(
208+
"lsmash-config.cmake.in"
209+
"${CMAKE_CURRENT_BINARY_DIR}/lsmash-config.cmake"
210+
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/lsmash"
211+
)
212+
install(
213+
FILES
214+
"${CMAKE_CURRENT_BINARY_DIR}/lsmash-config.cmake"
215+
"${CMAKE_CURRENT_BINARY_DIR}/lsmash-config-version.cmake"
216+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/lsmash"
217+
)
218+
install(
219+
EXPORT LSMASHTargets
220+
FILE LSMASHTargets.cmake
221+
NAMESPACE LSMASH::
222+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/lsmash"
223+
)
224+
225+
# --- Uninstall Target ---
226+
# (This part is identical to the obuparse solution)
227+
if(NOT TARGET uninstall)
228+
configure_file(
229+
"cmake_uninstall.cmake.in"
230+
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
231+
IMMEDIATE @ONLY
232+
)
233+
add_custom_target(uninstall
234+
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
235+
COMMENT "Uninstalling the project..."
236+
)
237+
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/lsmash")
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.")

lsmash-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}/LSMASHTargets.cmake")

0 commit comments

Comments
 (0)