From 7dd777db6a1c2be278740571cd5fdcd8bc21fbe1 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Sep 2024 05:25:44 +0900 Subject: [PATCH 1/3] build-sys: use AC_C_INLINE Signed-off-by: Masatake YAMATO --- configure.ac | 1 + main/inline.h | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1d7909e2a7..b3158618fa 100644 --- a/configure.ac +++ b/configure.ac @@ -260,6 +260,7 @@ AM_CONDITIONAL(ENABLE_DEBUGGING, [test "x$enable_debugging" = "xyes"]) AC_PROG_CC AC_PROG_CC_C99 +AC_C_INLINE # For gnulib. # Typically, this is immediately after AC_PROG_CC, ... gl_EARLY diff --git a/main/inline.h b/main/inline.h index 34ceb385f6..5d8f9120f6 100644 --- a/main/inline.h +++ b/main/inline.h @@ -11,7 +11,11 @@ #ifndef CTAGS_MAIN_INLINE_H #define CTAGS_MAIN_INLINE_H -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#ifdef HAVE_CONFIG_H +// AC_C_INLINE defines inline. The definition is in config.h. +#include "config.h" +# define CTAGS_INLINE static inline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L # define CTAGS_INLINE static inline #elif defined(_MSC_VER) # define CTAGS_INLINE static __inline From 1250b5c4b21eb4b131bc959bd21ebafa56cc46cf Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Sep 2024 05:28:23 +0900 Subject: [PATCH 2/3] build-sys: define READTAGS_INLINE See also c83bc89de1f79b3bf62498c9f8bffd0974e21fe1 of libreadtags. Signed-off-by: Masatake YAMATO --- Makefile.am | 1 + main/inline.h | 2 ++ mk_mingw.mak | 4 ++-- mk_mvc.mak | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index cf1149e7c4..4f493d091d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -95,6 +95,7 @@ readtags_CFLAGS = $(EXTRA_CFLAGS) $(WARNING_CFLAGS) $(COVERAGE_CFLAGS) dist_readtags_SOURCES = $(READTAGS_SRCS) $(READTAGS_HEADS) readtags_CPPFLAGS += $(GNULIB_CPPFLAGS) readtags_CPPFLAGS += -I$(srcdir)/dsl +readtags_CPPFLAGS += -DHAVE_CTAGS_INLINE_H readtags_LDADD = readtags_LDADD += $(GNULIB_LIBS) readtags_LDADD += libutil.a diff --git a/main/inline.h b/main/inline.h index 5d8f9120f6..5026434c04 100644 --- a/main/inline.h +++ b/main/inline.h @@ -27,4 +27,6 @@ # define CTAGS_INLINE static #endif +#define READTAGS_INLINE CTAGS_INLINE + #endif /* CTAGS_MAIN_INLINE_H */ diff --git a/mk_mingw.mak b/mk_mingw.mak index c1358cb2be..1e7ba140fb 100644 --- a/mk_mingw.mak +++ b/mk_mingw.mak @@ -116,8 +116,8 @@ $(RES_OBJ): win32/ctags.rc win32/ctags.exe.manifest win32/resource.h extra-cmds/%.o: extra-cmds/%.c $(V_CC) $(CC) -c $(OPT) $(CFLAGS) $(INCLUDES) -o $@ $< -libreadtags/%.o: libreadtags/%.c - $(V_CC) $(CC) -c $(OPT) $(CFLAGS) -Ilibreadtags -o $@ $< +libreadtags/%.o: libreadtags/%.c $(UTIL_HEADS) + $(V_CC) $(CC) -c $(OPT) $(CFLAGS) -Ilibreadtags $(INCLUDES) -DHAVE_CTAGS_INLINE_H -o $@ $< readtags.exe: $(READTAGS_OBJS) $(READTAGS_HEADS) $(UTIL_OBJS) $(UTIL_HEADS) $(READTAGS_DSL_OBJS) $(READTAGS_DSL_HEADS) $(GNULIB_OBJS) $(MINGW_GNULIB_HEADS) $(V_CC) $(CC) $(OPT) -o $@ $(READTAGS_OBJS) $(UTIL_OBJS) $(READTAGS_DSL_OBJS) $(GNULIB_OBJS) $(LIBS) diff --git a/mk_mvc.mak b/mk_mvc.mak index 01334061fe..b6255dc3b8 100644 --- a/mk_mvc.mak +++ b/mk_mvc.mak @@ -64,7 +64,7 @@ PDBFLAG = {extra-cmds}.c{extra-cmds}.obj:: $(CC) $(OPT) $(DEFINES) $(INCLUDES) /Foextra-cmds\ /c $< {libreadtags}.c{libreadtags}.obj:: - $(CC) $(OPT) $(DEFINES) $(INCLUDES) /Folibreadtags\ /c $< + $(CC) $(OPT) $(DEFINES) -DHAVE_CTAGS_INLINE_H $(INCLUDES) /Folibreadtags\ /c $< {dsl}.c{dsl}.obj:: $(CC) $(OPT) $(DEFINES) $(INCLUDES) /Fodsl\ /c $< {win32\mkstemp}.c{win32\mkstemp}.obj:: From 45c74a3f8b920f453753b4ae27040029c038421b Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Sun, 29 Sep 2024 11:00:03 +0900 Subject: [PATCH 3/3] Squashed 'libreadtags/' changes from d0210ee95..9137c94a8 9137c94a8 Merge pull request #58 from masatake/integrate-with-ctags-build-scripts c83bc89de Include inline.h only when HAVE_CTAGS_INLINE_H is defined 1cce44df3 Merge pull request #57 from masatake/inline d52b4a7c1 Put inline keyword on a hot spot function 47e754a1a Version 0.4.0 6c51577e2 Add CMakeLists.txt to EXTRA_DIST 8f8d10de7 Add libreadtags-uninstalled.pc.in 5498789a2 Merge pull request #54 from masatake/ctest 203ff54c2 Run the test cases with ctest f0bb08179 .gitignore: add the "build" dir and and the static library file b865829bc Merge pull request #53 from masatake/cmake ac09c2795 Write about supporting cmake in NEWS.md 1eea81110 Build the library with cmake as a test 85ec381b9 Write about the way to build the library with Autotools 9d49bd8aa Merge pull request #52 from masatake/circleci-on-fedora40 5cf863418 Add TODO items as comments to CMakeLists.txt 602ecd239 Add more comments for maintaining both configure.ac and CMakeLists.txt fda36837d Add a comment referencing to the document describing the library interface versions 96741abd0 Exemplify the relation between LT_VERSION and the string that can be passed -release option of libtool 1e60b0591 - Update README.md 96ec6aef8 - Update meta in CMakeLists.txt - Add options to build shared library - Update README.md 87dd003be - Update CMakeLists.txt to be compatible with C99 79d8b2ade Update CMake example in README.md 24bcdcb21 - Update README.md 537bb2c95 - Change to static library 9a20b5017 - Init CMake build system 80f339c0e Update the version of Fedora used in test git-subtree-dir: libreadtags git-subtree-split: 9137c94a807f7804eab3ca37a63673d0b21a918f --- .circleci/config.yml | 47 +++++++++++++-- .gitignore | 3 + CMakeLists.txt | 106 ++++++++++++++++++++++++++++++++++ Makefile.am | 2 +- NEWS.md | 26 +++++++++ README.md | 65 +++++++++++++++++++++ configure.ac | 16 ++++- libreadtags-uninstalled.pc.in | 14 +++++ readtags.c | 12 +++- test_inline.c | 7 +++ 10 files changed, 288 insertions(+), 10 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 libreadtags-uninstalled.pc.in create mode 100644 test_inline.c diff --git a/.circleci/config.yml b/.circleci/config.yml index 75d7340196..3dfa8e3fc1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,9 +1,43 @@ version: 2 jobs: - fedora31: + fedora40_cmake: working_directory: ~/libreadtags docker: - - image: docker.io/fedora:31 + - image: docker.io/fedora:40 + steps: + - run: + name: Install Git + command: | + yum -y install git + - checkout + - run: + name: Install build tools + command: | + yum -y install gcc cmake + - run: + name: Build + command: | + mkdir build + cmake -DCMAKE_BUILD_TYPE=Release -DLIBREADTAGS_BUILD_SHARED=ON -S . -B build + cmake --build build --target readtags + - run: + name: Build test cases + command: | + cmake --build build + - run: + name: Run the test cases + command: | + ctest --test-dir build || cat build/Testing/Temporary/LastTest.log + - run: + name: Install + command: | + cmake --build build --target install + test -e /usr/local/include/readtags.h + test -e /usr/local/lib/libreadtags.so + fedora40_autotools: + working_directory: ~/libreadtags + docker: + - image: docker.io/fedora:40 steps: - run: name: Install Git @@ -24,10 +58,10 @@ jobs: name: Test command: | make check VERBOSE=1 - fedora31_distcheck: + fedora40_distcheck: working_directory: ~/libreadtags docker: - - image: docker.io/fedora:31 + - image: docker.io/fedora:40 steps: - run: name: Install Git @@ -51,5 +85,6 @@ workflows: version: 2 build_and_test: jobs: - - fedora31 - - fedora31_distcheck + - fedora40_cmake + - fedora40_autotools + - fedora40_distcheck diff --git a/.gitignore b/.gitignore index 682ad0aa9e..7349962bf6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .deps .libs +*.a *.gcda *.gcno *.gcov @@ -46,3 +47,5 @@ tests/test-fix-unescaping-input-fields-exuberant tests/test-fix-unescaping-input-fields-no-mode tests/test-fix-unescaping-input-fields-backslash tests/test-fix-unescaping-input-fields-no-filesep + +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..f82ccf4990 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.22) +project( + readtags + # + # Synchronize VERSION with the value in configure.ac. + VERSION 0.4.0 + DESCRIPTION "a library for looking up tag entries in tag files" + HOMEPAGE_URL "https://github.com/universal-ctags/libreadtags" + LANGUAGES C +) + +set(CMAKE_C_STANDARD 99) + +option(LIBREADTAGS_BUILD_SHARED "Build shared/static library" OFF) + +# You don't have to edit API_VERSION. +# See https://cmake.org/cmake/help/latest/command/cmake_file_api.html +set(API_VERSION 1) +# +# Synchronize BUILD_VERSION with the value appended to libreadtags.so.<>. +# that is built with Autotools. +set(BUILD_VERSION 1.1.2) + +# Taken from https://gitlab.kitware.com/cmake/community/-/wikis/contrib/macros/TestInline +# Inspired from /usr/share/autoconf/autoconf/c.m4 +foreach(KEYWORD "inline" "__inline__" "__inline") + if(NOT DEFINED C_INLINE) + try_compile(C_HAS_${KEYWORD} "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/test_inline.c" + COMPILE_DEFINITIONS "-Dinline=${KEYWORD}") + if(C_HAS_${KEYWORD}) + SET(C_INLINE TRUE) + ADD_DEFINITIONS("-Dinline=${KEYWORD}") + endif(C_HAS_${KEYWORD}) + endif(NOT DEFINED C_INLINE) +endforeach(KEYWORD) +if(NOT DEFINED C_INLINE) + ADD_DEFINITIONS("-Dinline=") +endif(NOT DEFINED C_INLINE) + +if (LIBREADTAGS_BUILD_SHARED) + message(STATUS "Building shared library") + add_library(${PROJECT_NAME} SHARED readtags.c) + set_target_properties(${PROJECT_NAME} PROPERTIES + VERSION ${BUILD_VERSION} + SOVERSION ${API_VERSION} + PUBLIC_HEADER readtags.h + ) + install(TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION include + ) +else () + message(STATUS "Building static library") + add_library(${PROJECT_NAME} STATIC readtags.c) + install(TARGETS ${PROJECT_NAME} + ARCHIVE DESTINATION lib + PUBLIC_HEADER DESTINATION include + ) +endif () + +add_library(universal-ctags::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +enable_testing() +set(test_cases + test-api-tagsOpen + test-api-tagsFind + test-api-tagsFindPseudoTag + test-api-tagsFirstPseudoTag + test-api-tagsFirst + test-api-tagsClose + test-api-tagsSetSortType + + test-fix-unescaping + test-fix-null-deref + test-fix-large-tags + test-fix-unescaping-input-fields + test-fix-unescaping-input-fields-exuberant + test-fix-unescaping-input-fields-no-mode + test-fix-unescaping-input-fields-backslash + test-fix-unescaping-input-fields-no-filesep +) + +foreach(t IN LISTS test_cases) + add_executable(${t} tests/${t}.c) + target_link_libraries(${t} readtags) + add_test(NAME ${t} + COMMAND ${t} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) +endforeach() + +# +# TODO: +# +# * Support find_package +# +# ParticleG's comments quoted from +# https://github.com/universal-ctags/libreadtags/pull/51#issuecomment-2148017962 +# +# Actually, if we prepare CMakeList.txt properly, other CMake projects +# just need to use find_package method to load this package, see +# Finding Packages. But if you use CMake method FetchContent to add +# libreadtags to your project, then current changes should be enough. +# diff --git a/Makefile.am b/Makefile.am index a6e51a81eb..dad1d852d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS=-Wall -EXTRA_DIST = README.md NEWS.md +EXTRA_DIST = README.md NEWS.md CMakeLists.txt test_inline.c lib_LTLIBRARIES = libreadtags.la libreadtags_la_LDFLAGS = -no-undefined -version-info $(LT_VERSION) diff --git a/NEWS.md b/NEWS.md index b4f0904737..9f2aab8eff 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,29 @@ +# Version XXX + +- imporve performance; put inline keyword on a hot spot function. + + - before this change + + ``` + $ /bin/time ./readtags -t ~/.citre/kernel82.tags -l > /dev/null + 9.59user 0.42system 0:10.06elapsed 99%CPU (0avgtext+0avgdata 2819340maxresident)k + 0inputs+0outputs (0major+44149minor)pagefaults 0swaps + ``` + + - after this change + + ``` + $ /bin/time ./readtags -t ~/.citre/kernel82.tags -l > /dev/null + 7.82user 0.43system 0:08.30elapsed 99%CPU (0avgtext+0avgdata 2819688maxresident)k + 0inputs+0outputs (0major+44138minor)pagefaults 0swaps + ``` + +# Version 0.4.0 + +- support cmake as a build system (ParticleG ) + +- add libreadtags-uninstalled.pc.in. + # Version 0.3.0 - fix calls to ctype functions (Colomban Wendling ) diff --git a/README.md b/README.md index 5c2fb80fcd..ead497687a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# libreadtags + libreadtags is a library for reading tags files generated by ctags. libreadtags assumes the tags file format explained in [tags(5)](https://docs.ctags.io/en/latest/man/tags.5.html) of Universal-ctags. @@ -10,3 +12,66 @@ NEWS.md describes note worty changes. If you are looking for command line interface for tags files, you will like [readtags command](https://docs.ctags.io/en/latest/man/readtags.1.html) shipped as part of Universal-ctags. It uses libreadtags extensively. + +You can build libreadtags with GNU Autotools and CMake. + +## Autotools Usage + +### Build +```shell +test -e autogen.sh && ./autogen.sh +./configure +make +``` + +### Test +```shell +make check +``` + + +## CMake Usage + +### Build as a standalone project + +#### Configure and build only + +```shell +mkdir build +cmake -DCMAKE_BUILD_TYPE=Release -DLIBREADTAGS_BUILD_SHARED=ON -S . -B build +cmake --build build --target readtags +``` + +#### Configure, build, and test +```shell +mkdir build +cmake -DCMAKE_BUILD_TYPE=Release -DLIBREADTAGS_BUILD_SHARED=ON -S . -B build +cmake --build build +ctest --test-dir build +``` + +#### Configure and install + +This will install the library and headers to `/usr/local`. + +```shell +mkdir build +cmake -DCMAKE_BUILD_TYPE=Release -DLIBREADTAGS_BUILD_SHARED=ON -S . -B build +sudo cmake --build build --target install +``` + +### Integrate into other CMake projects + +```cmake +include(FetchContent) + +FetchContent_Declare( + readtags + GIT_REPOSITORY https://github.com/universal-ctags/libreadtags.git + GIT_TAG master +) + +FetchContent_MakeAvailable(readtags) + +target_link_libraries(your_target PRIVATE universal-ctags::readtags) +``` diff --git a/configure.ac b/configure.ac index c48b894569..466fa91403 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,7 @@ # -*- Autoconf -*- -AC_INIT(libreadtags, 0.3.0) +# +# When updating the above version, you also update VERSION in CMakeList.txt. +AC_INIT(libreadtags, 0.4.0) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([readtags.c]) @@ -8,7 +10,8 @@ AC_PROG_LIBTOOL # LT_VERSION => CURRENT[:REVISION[:AGE]] # -# (the following instructions are taken from configure.ac in libskk) +# (the following instructions are taken from configure.ac in libskk +# See also "7 Library interface versions" in the libtool info document.) # # If library source has changed since last release, increment revision # If public symbols have been added, removed or changed since last release, @@ -20,20 +23,27 @@ AC_PROG_LIBTOOL # # 0:0:0 # initial version; API is the same as readtags.h in Exuberant-ctags. +# (libreadtags.so.0.0.0) # # 1:0:0 # introduced tagsGetErrno() and tagErrno. # rename sortType to tagSortType. +# (libreadtags.so.1.0.0) # # 2:0:1 # introduced TagErrnoFileMayTooBig. # introduced tagsFindPseudoTag. +# (libreadtags.so.1.1.0) # # 2:1:1 # no change in public interface. +# (libreadtags.so.1.1.1) # # 2:2:1 # no change in public interface. +# (libreadtags.so.1.1.2) +# +# When updating LT_VERSION, update BUILD_VERSION of CMakeLists.txt. # AC_SUBST(LT_VERSION, [2:2:1]) @@ -46,8 +56,10 @@ fi AC_SUBST([GCOV_CFLAGS]) AC_PROG_CC_C99 +AC_C_INLINE AC_CONFIG_FILES([Makefile libreadtags.pc + libreadtags-uninstalled.pc tests/Makefile]) AC_OUTPUT diff --git a/libreadtags-uninstalled.pc.in b/libreadtags-uninstalled.pc.in new file mode 100644 index 0000000000..67fe521930 --- /dev/null +++ b/libreadtags-uninstalled.pc.in @@ -0,0 +1,14 @@ +abs_top_srcdir=@abs_top_srcdir@ +abs_top_builddir=@abs_top_builddir@ + +prefix= +exec_prefix= +libdir=${abs_top_builddir} +includedir=${abs_top_builddir} + +Name: libreadtags Uninstalled +Description: a library for looking up tag entries in tag files (Uninstalled) +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lreadtags +Cflags: -I${includedir} diff --git a/readtags.c b/readtags.c index 45488c36a8..acf9170c05 100644 --- a/readtags.c +++ b/readtags.c @@ -9,6 +9,15 @@ /* * INCLUDE FILES */ +#ifdef HAVE_CTAGS_INLINE_H +/* the build script of ctags can insert thee macro + definition for READTAGS_INLINE. */ +#include "inline.h" +#else +/* Makefile generated by configure defines inline. */ +#define READTAGS_INLINE static inline +#endif + #include #include #include @@ -151,7 +160,8 @@ static int xdigitValue (unsigned char digit) * Reads the first character from the string, possibly un-escaping it, and * advances *s to the start of the next character. */ -static int readTagCharacter (const char **const s) +READTAGS_INLINE +int readTagCharacter (const char **const s) { const unsigned char *p = (const unsigned char *) *s; int c = *p; diff --git a/test_inline.c b/test_inline.c new file mode 100644 index 0000000000..06db632308 --- /dev/null +++ b/test_inline.c @@ -0,0 +1,7 @@ +/* Taken from https://gitlab.kitware.com/cmake/community/-/wikis/contrib/macros/TestInline + * for using "inline" with cmake build. */ +/* Test source lifted from /usr/share/autoconf/autoconf/c.m4 */ +typedef int foo_t; +static inline foo_t static_foo(){return 0;} +foo_t foo(){return 0;} +int main(int argc, char *argv[]){return 0;}