Use idiomatic GNUInstallDirs for all install paths; fix pkg-config and relocatability#1063
Use idiomatic GNUInstallDirs for all install paths; fix pkg-config and relocatability#1063
Conversation
- Apply PR #1062 changes: DIR_INCLUDE → CMAKE_INSTALL_INCLUDEDIR, DIR_ETC → CMAKE_INSTALL_SYSCONFDIR, DIR_LIBRARY → CMAKE_INSTALL_LIBDIR - Similarly update DIR_SHARE → CMAKE_INSTALL_FULL_DATAROOTDIR (absolute, required because it feeds PKGDATADIR/LOCALEDIR compile-time definitions) - Remove LIB_INSTALL_DIR CACHE variable and LIB_SUFFIX dead code (LIB_SUFFIX was only used to compute DIR_LIBRARY which now uses CMAKE_INSTALL_LIBDIR directly; LIB_INSTALL_DIR was a CACHE variable always overriding DIR_LIBRARY with the same value) - Remove LIB_INSTALL_DIR override block - Fix opencc.pc.in: use CMAKE_INSTALL_FULL_LIBDIR and CMAKE_INSTALL_FULL_INCLUDEDIR for absolute pkg-config paths (GNUInstallDirs relative paths would produce broken -L/-I flags) - Add comments explaining relative vs absolute path choice Co-authored-by: BYVoid <245270+BYVoid@users.noreply.github.com> Agent-Logs-Url: https://github.com/BYVoid/OpenCC/sessions/a2b64015-d200-4d3d-b473-55a9be50c4b6
Each new variable (CMAKE_INSTALL_INCLUDEDIR, CMAKE_INSTALL_SYSCONFDIR, CMAKE_INSTALL_LIBDIR, CMAKE_INSTALL_FULL_DATAROOTDIR) now has inline documentation showing: - Link to https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html - Default relative/absolute values for common prefixes (/usr/local, /usr) - The old hardcoded path each variable replaces - SYSCONFDIR special case: /usr prefix gives /etc (not /usr/etc) Co-authored-by: BYVoid <245270+BYVoid@users.noreply.github.com> Agent-Logs-Url: https://github.com/BYVoid/OpenCC/sessions/4d6d1872-e7f6-4eb6-bf48-930c0d22928b
BYVoid
left a comment
There was a problem hiding this comment.
Thanks for the cleanup — using GNUInstallDirs properly is the right direction. The verbose documentation block is a nice touch for future maintainers. A few issues to address before merging:
Summary of concerns:
-
pkg-config regression:
opencc.pc.innow usesCMAKE_INSTALL_FULL_*variables directly, which bypasses the legacy override variables (INCLUDE_INSTALL_DIR,LIB_INSTALL_DIR, etc.) that the CMakeLists.txt still supports. A packager using-DINCLUDE_INSTALL_DIR=/custom/pathwould get the right install layout but a broken.pcfile. -
Inconsistent removal of
LIB_INSTALL_DIR: The override block forLIB_INSTALL_DIRis removed whileSHARE_INSTALL_PREFIX,INCLUDE_INSTALL_DIR, andSYSCONF_INSTALL_DIRare kept. Either remove all legacy overrides (with a migration note) or keep all of them. -
Mixed relative/absolute
DIR_*variables:DIR_SHAREis absolute (CMAKE_INSTALL_FULL_DATAROOTDIR) while the otherDIR_*variables are relative. This works but is confusing. Consider keeping all relative and only using the absolute form in theadd_definitions()call where it's actually needed. -
Dead variable:
DIR_PREFIXis no longer used by anything — can be removed.
The core idea is sound, but the interaction between the new GNUInstallDirs variables and the retained legacy override variables needs to be reconciled to avoid subtle breakage for downstream packagers.
| set (DIR_PREFIX ${CMAKE_INSTALL_PREFIX}) | ||
| set (DIR_INCLUDE ${DIR_PREFIX}/include) | ||
| set (DIR_SHARE ${DIR_PREFIX}/share) | ||
| set (DIR_ETC ${DIR_PREFIX}/etc) | ||
| set (DIR_LIBRARY ${DIR_PREFIX}/lib${LIB_SUFFIX}) | ||
| # Relative paths are used for install() destinations and CMake package config | ||
| # so that packages remain relocatable. | ||
| set (DIR_INCLUDE ${CMAKE_INSTALL_INCLUDEDIR}) |
There was a problem hiding this comment.
Inconsistency: DIR_SHARE is absolute while DIR_INCLUDE, DIR_ETC, DIR_LIBRARY are relative.
DIR_SHARE is set to CMAKE_INSTALL_FULL_DATAROOTDIR (absolute), while the other three use relative GNUInstallDirs variables. The comment explains this is because DIR_SHARE feeds into PKGDATADIR/LOCALEDIR compile-time macros that need absolute paths — that reasoning is sound.
However, DIR_SHARE_OPENCC (derived from DIR_SHARE) is also used as an install(DESTINATION ...) in data/CMakeLists.txt. While CMake does handle absolute DESTINATION paths correctly (including DESTDIR support), mixing relative and absolute destinations in the same project is unusual and can be confusing for future maintainers.
Consider either:
- Making all
DIR_*variables relative and only usingCMAKE_INSTALL_FULL_DATAROOTDIRspecifically in theadd_definitions()call for the compile-time macros, or - Making all
DIR_*variables absolute (usingFULL_variants) for consistency.
Option 1 is the more idiomatic CMake approach — use relative paths for install() destinations and absolute paths only where truly needed (compile-time defines).
There was a problem hiding this comment.
Fixed in 31771ff. DIR_SHARE is now set to the relative CMAKE_INSTALL_DATAROOTDIR (like all other DIR_* variables). Absolute paths are only computed on-demand via a foreach block that applies an IS_ABSOLUTE check — the result is stored in DIR_SHARE_FULL, DIR_INCLUDE_FULL, and DIR_LIBRARY_FULL, which are used exclusively where absolute paths are required: add_definitions(-DPKGDATADIR=...) and the pkg-config template.
| prefix=@CMAKE_INSTALL_PREFIX@ | ||
| exec_prefix=${prefix} | ||
| libdir=@DIR_LIBRARY@ | ||
| includedir=@DIR_INCLUDE@ | ||
| libdir=@CMAKE_INSTALL_FULL_LIBDIR@ | ||
| includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ |
There was a problem hiding this comment.
Bug: pkg-config now ignores user-provided override variables.
The old .pc.in used @DIR_LIBRARY@ and @DIR_INCLUDE@, which reflected any user overrides via LIB_INSTALL_DIR, INCLUDE_INSTALL_DIR, etc. The new version uses @CMAKE_INSTALL_FULL_LIBDIR@ and @CMAKE_INSTALL_FULL_INCLUDEDIR@ directly, which bypass those overrides entirely.
For example, if a packager passes -DINCLUDE_INSTALL_DIR=/custom/include, the CMakeLists.txt still updates DIR_INCLUDE accordingly (line 99), but the .pc file now ignores it and uses the GNUInstallDirs default instead. This is a regression for downstream users relying on those override variables.
To fix this, either:
- Keep using
@DIR_INCLUDE@and@DIR_LIBRARY@in the.pc.in, but ensure those variables are set to absolute paths (e.g., prepend${CMAKE_INSTALL_PREFIX}/when the GNUInstallDirs value is relative), or - Remove the legacy override variables entirely (see my other comment about
LIB_INSTALL_DIR).
There was a problem hiding this comment.
Fixed in 31771ff. opencc.pc.in now uses @DIR_LIBRARY_FULL@ and @DIR_INCLUDE_FULL@. These variables are computed after all legacy overrides (LIB_INSTALL_DIR, INCLUDE_INSTALL_DIR, etc.) have been applied, using an IS_ABSOLUTE check to correctly handle both relative GNUInstallDirs defaults and user-supplied absolute paths.
| if (DEFINED LIB_INSTALL_DIR) | ||
| set (DIR_LIBRARY ${LIB_INSTALL_DIR}) | ||
| endif (DEFINED LIB_INSTALL_DIR) |
There was a problem hiding this comment.
Breaking change: LIB_INSTALL_DIR override removed but similar overrides kept.
The LIB_INSTALL_DIR override block is removed, but SHARE_INSTALL_PREFIX, INCLUDE_INSTALL_DIR, and SYSCONF_INSTALL_DIR are all kept. This is inconsistent — either all legacy overrides should be removed (with a migration note in the PR description pointing users to -DCMAKE_INSTALL_LIBDIR=... instead), or all should be kept for backward compatibility.
Some Linux distro packaging scripts (e.g., older KDE/ECM-style specs) pass -DLIB_INSTALL_DIR=... explicitly. Removing this silently could break their builds without any error — it would just install to the wrong path.
Suggestion: Either keep the LIB_INSTALL_DIR override for consistency, or remove all legacy overrides and document the migration to standard GNUInstallDirs variables (CMAKE_INSTALL_LIBDIR, CMAKE_INSTALL_INCLUDEDIR, CMAKE_INSTALL_SYSCONFDIR, CMAKE_INSTALL_DATAROOTDIR).
There was a problem hiding this comment.
Fixed in 31771ff. The LIB_INSTALL_DIR override block is restored. All four legacy overrides (SHARE_INSTALL_PREFIX, INCLUDE_INSTALL_DIR, SYSCONF_INSTALL_DIR, LIB_INSTALL_DIR) are now treated consistently.
| # Full/absolute form is required here because the value is baked into the | ||
| # binary as PKGDATADIR/LOCALEDIR at compile time for runtime data lookup. | ||
|
|
||
| set (DIR_PREFIX ${CMAKE_INSTALL_PREFIX}) |
There was a problem hiding this comment.
Nit: DIR_PREFIX is now unused except as a vestigial variable.
With DIR_INCLUDE, DIR_SHARE, DIR_ETC, and DIR_LIBRARY no longer derived from DIR_PREFIX, this variable has no remaining consumers (it was only referenced in opencc.pc.in which now uses CMAKE_INSTALL_PREFIX directly). Consider removing it to avoid dead code.
…_INSTALL_DIR, fix pc.in - Make DIR_SHARE relative (CMAKE_INSTALL_DATAROOTDIR) like all other DIR_* variables - Compute DIR_*_FULL absolute variants (via IS_ABSOLUTE check) for uses that require absolute paths: add_definitions(PKGDATADIR/LOCALEDIR) and the pc file - Restore LIB_INSTALL_DIR override block (removed in previous commit) so all four legacy overrides are now treated consistently - Remove dead DIR_PREFIX variable - Fix opencc.pc.in: use @DIR_LIBRARY_FULL@ / @DIR_INCLUDE_FULL@ so legacy override variables (LIB_INSTALL_DIR, INCLUDE_INSTALL_DIR) are correctly reflected in the generated pkg-config file - Update parity comment: s/CMAKE_INSTALL_FULL_DATAROOTDIR/CMAKE_INSTALL_DATAROOTDIR/ Co-authored-by: BYVoid <245270+BYVoid@users.noreply.github.com> Agent-Logs-Url: https://github.com/BYVoid/OpenCC/sessions/4215d006-8491-4f30-a125-94c14523e0e3
All four points addressed in 31771ff:
|
BYVoid
left a comment
There was a problem hiding this comment.
All previous concerns have been addressed cleanly:
- Relative/absolute consistency: All
DIR_*variables are now relative, withDIR_*_FULLabsolute variants computed on-demand viaforeach+IS_ABSOLUTE— this is the idiomatic approach. - pkg-config override support:
opencc.pc.innow usesDIR_LIBRARY_FULL/DIR_INCLUDE_FULL, which correctly reflect legacy overrides. LIB_INSTALL_DIRrestored: All four legacy override variables are handled consistently.DIR_PREFIXremoved: No dead code.
One minor nit left inline (duplicated /opencc and /locale suffixes in add_definitions), but nothing blocking. LGTM.
| -DPKGDATADIR="${DIR_SHARE_FULL}/opencc" | ||
| -DLOCALEDIR="${DIR_SHARE_FULL}/locale" |
There was a problem hiding this comment.
Nit: DIR_SHARE_OPENCC and DIR_SHARE_LOCALE are already defined above (lines 125-126) as ${DIR_SHARE}/opencc and ${DIR_SHARE}/locale. Here the /opencc and /locale suffixes are duplicated with DIR_SHARE_FULL.
Not a correctness issue since both produce the same result, but you could consider adding a DIR_SHARE_OPENCC_FULL / DIR_SHARE_LOCALE_FULL alongside the existing derived variables to keep the suffix in one place, or just reference these directly as ${DIR_SHARE_FULL}/opencc. Either way is fine — just flagging the duplication.
Deeper review — downstream consumer analysisI traced all consumers of the Improved behavior (bonus)
Verified correct — no issues
Minor observations (non-blocking)
CI statusSeveral checks already passing (sort-check, CodeQL, Analyze, some Node.js and Python builds). Remaining builds still in progress — no failures observed. |
…avoid suffix duplication Introduce DIR_SHARE_OPENCC_FULL and DIR_SHARE_LOCALE_FULL by appending the /opencc and /locale suffixes to DIR_SHARE_FULL once, keeping the suffix in a single location. Use these in add_definitions() instead of inline expansion. Co-authored-by: BYVoid <245270+BYVoid@users.noreply.github.com> Agent-Logs-Url: https://github.com/BYVoid/OpenCC/sessions/81a83abd-8b46-4cdb-9768-6ccaeeb287e9
DIR_SHARE_LOCALE (relative) was only defined but never consumed. DIR_SHARE_LOCALE_FULL was only used in add_definitions(), where the suffix /locale can be inlined directly against DIR_SHARE_FULL. Keep DIR_SHARE_OPENCC (used by install() in data/ and doc/) and DIR_SHARE_OPENCC_FULL (used in add_definitions()) as both are needed. Co-authored-by: BYVoid <245270+BYVoid@users.noreply.github.com> Agent-Logs-Url: https://github.com/BYVoid/OpenCC/sessions/8bb2a2da-c659-4eaf-bec0-07ee0a2d3eb0
|
Inconsistency: After the latest commits, add_definitions(
-DPKGDATADIR="${DIR_SHARE_OPENCC_FULL}"
-DLOCALEDIR="${DIR_SHARE_FULL}/locale" # ← inconsistent
)Meanwhile Fix: restore set (DIR_SHARE_OPENCC ${DIR_SHARE}/opencc)
set (DIR_SHARE_LOCALE ${DIR_SHARE}/locale)
# ... foreach block ...
set (DIR_SHARE_OPENCC_FULL ${DIR_SHARE_FULL}/opencc)
set (DIR_SHARE_LOCALE_FULL ${DIR_SHARE_FULL}/locale)
# ...
add_definitions(
-DPKGDATADIR="${DIR_SHARE_OPENCC_FULL}"
-DLOCALEDIR="${DIR_SHARE_LOCALE_FULL}"
)I've pushed this fix to |
Restore DIR_SHARE_LOCALE and add DIR_SHARE_LOCALE_FULL so both compile-time macros (PKGDATADIR, LOCALEDIR) use dedicated _FULL variables instead of mixing variable and inline suffix styles.
Summary
Replace all hardcoded
${CMAKE_INSTALL_PREFIX}/...path constructions inCMakeLists.txtwith proper GNUInstallDirs variables, fix the pkg-config template to respect user override variables, and remove dead code.Changes
CMakeLists.txtRelative
DIR_*variables via GNUInstallDirs — AllDIR_*variables now use relative paths (idiomatic CMake forinstall()destinations and relocatable package config):/usr/local//usr${CMAKE_INSTALL_PREFIX}/includeCMAKE_INSTALL_INCLUDEDIRinclude${CMAKE_INSTALL_PREFIX}/etcCMAKE_INSTALL_SYSCONFDIRetc//etc¹${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}CMAKE_INSTALL_LIBDIRlib(also handleslib64, multiarch ²)${CMAKE_INSTALL_PREFIX}/shareCMAKE_INSTALL_DATAROOTDIRshareAbsolute
DIR_*_FULLvariants on demand — Aforeachblock with anIS_ABSOLUTEguard computesDIR_SHARE_FULL,DIR_INCLUDE_FULL, andDIR_LIBRARY_FULL. These are used only where absolute paths are truly required:PKGDATADIR,LOCALEDIR) — needed at runtime to locate dictionaries and config filesopencc.pc.inpkg-config templateDead code removal:
LIB_SUFFIX/LIB_INSTALL_DIRCACHE logic (superseded byCMAKE_INSTALL_LIBDIR)DIR_PREFIXvariable (no remaining consumers afteropencc.pc.inswitched toCMAKE_INSTALL_PREFIX)Legacy override consistency — All four legacy override variables are preserved and handled consistently:
SHARE_INSTALL_PREFIX→DIR_SHAREINCLUDE_INSTALL_DIR→DIR_INCLUDESYSCONF_INSTALL_DIR→DIR_ETCLIB_INSTALL_DIR→DIR_LIBRARYopencc.pc.inprefixnow uses@CMAKE_INSTALL_PREFIX@directly (was@DIR_PREFIX@, now removed)libdir/includedirnow use@DIR_LIBRARY_FULL@/@DIR_INCLUDE_FULL@— these are computed after all legacy overrides are applied, so user-supplied-DINCLUDE_INSTALL_DIR=/custom/pathis correctly reflected (was broken in an earlier revision)Side-effect improvements
$<INSTALL_INTERFACE>insrc/CMakeLists.txtandconfigure_package_config_file(PATH_VARS DIR_INCLUDE)now receive relative paths, makingOpenCCConfig.cmakeproperly relocatableCMAKE_INSTALL_LIBDIRhandleslib/x86_64-linux-gnuetc., which the oldLIB_SUFFIXapproach could notFiles changed
CMakeLists.txt— install directory logic rewrite (+27 lines, −10 lines net)opencc.pc.in— switch to absolute_FULLvariables andCMAKE_INSTALL_PREFIX