OS specific instructions in CMAKE: How to?

C++LinuxCmakeMingwPortability

C++ Problem Overview


I am a beginner to CMAKE. Below is a simple cmake file which works well in mingw environment windows. The problem is clearly with target_link_libraries() function of CMAKE where I am linking libwsock32.a. In windows this works and I get the results.

However, as expected, in Linux, the /usr/bin/ld will look for -lwsock32 which is NOT there on the Linux OS.

My Problem is: How do I instruct CMAKE to avoid linking wsock32 library in Linux OS???

Any help will be greatly appreciated.

My Simple CMake file:

 PROJECT(biourl)
 set (${PROJECT_NAME}_headers ./BioSocketAddress.h  ./BioSocketBase.h ./BioSocketBuffer.h ./BioSocketCommon.h  ./BioSocketListener.h  ./BioSocketPrivate.h  ./BioSocketStream.h ./BioUrl.h BioDatabase.h )

set (${PROJECT_NAME}_sources BioSocketAddress.C  BioSocketBase.C  BioSocketCommon.C BioSocketStream.C  BioUrl.C BioDatabase.C )

add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_headers} ${${PROJECT_NAME}_sources} )

# linkers
#find_library(ws NAMES wsock32 PATHS ${PROJECT_SOURCE_DIR} NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH)

target_link_libraries(${PROJECT_NAME} bioutils wsock32)

install (TARGETS ${PROJECT_NAME}
       RUNTIME DESTINATION bin
       LIBRARY DESTINATION lib
       ARCHIVE DESTINATION lib/archive )

C++ Solutions


Solution 1 - C++

Use

if (WIN32)
    #do something
endif (WIN32)

or

if (UNIX)
    #do something
endif (UNIX)

or

if (MSVC)
    #do something
endif (MSVC)

or similar

see CMake Useful Variables and CMake Checking Platform

Solution 2 - C++

Given this is such a common issue, geronto-posting:

	if(UNIX AND NOT APPLE)
	    set(LINUX TRUE)
	endif()

	# if(NOT LINUX) should work, too, if you need that
	if(LINUX) 
	    message(STATUS ">>> Linux")
	    # linux stuff here
	else()
	    message(STATUS ">>> Not Linux")
	    # stuff that should happen not on Linux 
	endif()

CMake boolean logic docs

CMake platform names, etc.

Solution 3 - C++

In General

You can detect and specify variables for several operating systems like that:

Detect Microsoft Windows
if(WIN32)
    # for Windows operating system in general
endif()

Or:

if(MSVC OR MSYS OR MINGW)
    # for detecting Windows compilers
endif()
Detect Apple MacOS
if(APPLE)
    # for MacOS X or iOS, watchOS, tvOS (since 3.10.3)
endif()
Detect Unix and Linux
if(UNIX AND NOT APPLE)
    # for Linux, BSD, Solaris, Minix
endif()

Your specific linker issue

To solve your issue with the Windows-specific wsock32 library, just remove it from other systems, like that:

if(WIN32)
    target_link_libraries(${PROJECT_NAME} bioutils wsock32)
else
    target_link_libraries(${PROJECT_NAME} bioutils)
endif()

Solution 4 - C++

You have some special words from CMAKE, take a look:

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
    // do something for Linux
else
    // do something for other OS

Solution 5 - C++

Generator expressions are also possible:

target_link_libraries(
    target_name
    PUBLIC
        libA
        $<$<PLATFORM_ID:Windows>:wsock32>
    PRIVATE
        $<$<PLATFORM_ID:Linux>:libB>
        libC
)

This will link libA, wsock32 & libC on Windows and link libA, libB & libC on Linux

CMake Generator Expressions

Solution 6 - C++

Try that:

if(WIN32)
    set(ADDITIONAL_LIBRARIES wsock32)
else()
    set(ADDITIONAL_LIBRARIES "")
endif()

target_link_libraries(${PROJECT_NAME} bioutils ${ADDITIONAL_LIBRARIES})

You can find other useful variables here.

Solution 7 - C++

Modern CMake Way

Avoid using WIN32, APPLE, etc. Excerpt of a moderator's reply on official forum:

> The WIN32, APPLE, UNIX, etc. variables are “soft” deprecated [...] CMAKE_SYSTEM_NAME is what I’d use in CMake code, PLATFORM_ID is needed in generator expressions.

What possible values can CMAKE_SYSTEM_NAME or PLAFORM_ID take? Refer the source.

How to detect a platform

Use STREQUAL:

if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
  # Linux-specific stuff
endif ()

How to detect multiple platforms

Create a list variable and use IN_LIST:

set(OPENGL_PLATFORMS Linux Windows)
if (CMAKE_SYSTEM_NAME IN_LIST OPENGL_PLATFORMS)
  # platform-specific stuff e.g.
  find_package(OpenGL REQUIRED)
endif ()

Generator Expression

Use PLATFORM_ID:

target_link_libraries(TARGET_NAME PRIVATE
  $<$<PLATFORM_ID:Linux,Windows>:OpenGL::GL>)

Aside: Generator expressions can only be used if the manual calls it out. For example target_link_libraries's documentation calls it out while set_target_properties doesn't. I'd to read https://stackoverflow.com/questions/67180311/cmake-set-target-properties-fails-with-target-defined-by-generator-expression to realize why.

Solution 8 - C++

I want to leave this here because I struggled with this when compiling for Android in Windows with the Android SDK.

CMake distinguishes between TARGET and HOST platform.

My TARGET was Android so the variables like CMAKE_SYSTEM_NAME had the value "Android" and the variable WIN32 from the other answer here was not defined. But I wanted to know if my HOST system was Windows because I needed to do a few things differently when compiling on either Windows or Linux or IOs. To do that I used CMAKE_HOST_SYSTEM_NAME which I found is barely known or mentioned anywhere because for most people TARGEt and HOST are the same or they don't care.

Hope this helps someone somewhere...

Solution 9 - C++

Use some preprocessor macro to check if it's in windows or linux. For example

#ifdef WIN32
LIB= 
#elif __GNUC__
LIB=wsock32
#endif

include -l$(LIB) in you build command.

You can also specify some command line argument to differentiate both.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPrasadView Question on Stackoverflow
Solution 1 - C++relaxxxView Answer on Stackoverflow
Solution 2 - C++mlvljrView Answer on Stackoverflow
Solution 3 - C++q9fView Answer on Stackoverflow
Solution 4 - C++Bruno SoaresView Answer on Stackoverflow
Solution 5 - C++CascadesView Answer on Stackoverflow
Solution 6 - C++tiburView Answer on Stackoverflow
Solution 7 - C++legends2kView Answer on Stackoverflow
Solution 8 - C++Nico HeidtkeView Answer on Stackoverflow
Solution 9 - C++Barun ParichhaView Answer on Stackoverflow