Problem with *general* library name

The following project builds successfully:

// foo.cpp
void foo() {}

// bar.cpp
void foo();
void main() { foo(); }

project(p)
add_library(general foo.cpp)
link_libraries(general)
add_executable(foo bar.cpp)

Let us modernize it with target_link_libraries:

project(p)
add_library(general foo.cpp)
add_executable(foo bar.cpp)
target_link_libraries(foo general)

We have an error:

CMake Error at CMakeLists.txt:4 (target_link_libraries):
The “general” argument must be followed by a library.

The problem is that general is a keyword within target_link_libraries()

Is there a way to escape the library name?

see syntax for target_link_libraries

p.s. which version of cmake do you use?

OK, this seems to work:

target_link_libraries(foo $<1:general>)

@ben.boeckel is this a bug or a feature?

see https://cmake.org/cmake/help/latest/command/link_libraries.html

general, debug, optimized are reserved, not usable as library names?

cmake_minimum_required(VERSION 4.2...4.3)

project(p LANGUAGES CXX)

add_library(optimized STATIC)
target_sources(optimized PRIVATE foo.cpp)

add_executable(bar bar.cpp)
target_link_libraries(bar PRIVATE optimized)

https://cmake.org/cmake/help/latest/command/link_libraries.html states that debug|optimized|general are keywords in link_libraries(), which seems to be not the case. Our example shows this is true only for target_link_libraries()

Note that debug|optimized|general are unusual for CMake because they are case sensitive.

The library names General or Optimized are fine. Maybe these keywords should have been made all-uppercase.

The debug, optimized and general keywords are from very old CMake days. So old that most folks are not even aware they exist. They should not be used in any project today. I also recommend you don’t name a target any of those specific names, for reasons like the one you’re posting about here. All three are not good names for a target anyway, and general in particular is overly… general.

Sometimes we do not have control over naming. For (real life) example, there might be a schema file general.xsd, then a framework must generate a library project named general.

Maybe phase them out?

Yes, a target-policy to indicate that these indicators are not used would be useful I think.

Cc: @brad.king

1 Like

The general, debug, and optimized keywords are meaningful only in target_link_libraries arguments (and maybe link_libraries). They are still used by find modules, both upstream and in the wild, through SelectLibraryConfigurations, in order to report Foo_LIBRARIES as a single result variable:

set(Foo_LIBRARIES optimized ${Foo_LIBRARY_RELEASE} debug ${Foo_LIBRARY_DEBUG})

This is left from pre-imported-target style find modules where the result is expected to be used like this:

target_link_libraries(consumer PRIVATE ${Foo_LIBRARIES})

In general such legacy result variables from find modules are not expected to have generator expressions in them. I don’t think we can stop supporting this use case, as it was pervasive at one time and likely has a huge legacy ecosystem.

The above-suggested $<1:general> is a good workaround to prevent target_link_libraries from treating it as a keyword.