cmake native binary during cross-compile - cmake

I'm trying to build a native binary for using during a cross-compile, but CMAKE_CROSSCOMPILING always seems to be set so the ${EXPORT_FILE} never gets the native binary and the ADD_CUSTOM_COMMAND complains that native-uberplac is not found.
Does anyone know how this is supposed to work?
set(EXPORT_FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake) file(WRITE ${EXPORT_FILE})
if(CMAKE_CROSSCOMPILING) MESSAGE(INFO "***CMAKE_CROSSCOMPILING SET***") SET(IMPORT_EXECUTABLES ${EXPORT_FILE}) include(${IMPORT_EXECUTABLES}) endif(CMAKE_CROSSCOMPILING)
add_executable(uberplac src/host/uberplac.c) SET_TARGET_PROPERTIES(uberplac PROPERTIES COMPILE_DEFINITIONS "${TARGET_ARCH}") CHECK_LIBRARY_EXISTS(m sin "" uberplac_USE_LIBM) if(uberplac_USE_LIBM) TARGET_LINK_LIBRARIES(uberplac m) endif()
IF(CMAKE_CROSSCOMPILING) SET(uberplac_EXE native-uberplac) ELSE(CMAKE_CROSSCOMPILING) SET(uberplac_EXE uberplac) ENDIF(CMAKE_CROSSCOMPILING)
IF(NOT CMAKE_CROSSCOMPILING) MESSAGE(INFO "***CMAKE_CROSSCOMPILING NOT SET***") EXPORT(TARGETS uberplac FILE ${EXPORT_FILE} NAMESPACE native- ) ENDIF(NOT CMAKE_CROSSCOMPILING)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/van_arch.h COMMAND ${uberplac_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/torpid/torpid.py ${ASM_FLAGS} -o ${CMAKE_CURRENT_BINARY_DIR}/van_arch.h ${CMAKE_CURRENT_SOURCE_DIR}/src/vm_${ASM_ARCH}.asc DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/torpid/torpid.py uberplac )

Related

How to add dependencies to a custom_target() after the fact?

I'm trying to have a top level target, we'll call it sdk_extraction that is tested/built every time, and had depends on a bunch of generated files that are basically copies or minor transformations of files in the tree.
I build up the list of files to export as a property string/list, then when it's all said and done take that list and iterate through it, creating custom_commands for each one and then adding a dependency between the output file and the sdk_extraction target.
function(finalize_sdk_export destination)
file(REAL_PATH ${destination} destination )
add_custom_target(sdk_target ALL
COMMENT "Exporting SDK"
)
get_property(sdk_source GLOBAL PROPERTY SDK_SOURCE )
string(REPLACE " " ";" sdk_source "${sdk_source}")
foreach (item ${sdk_source})
string(REPLACE ${destination} ${destination}/sdk target "${item}")
add_custom_command(
OUTPUT ${target}
DEPENDS ${item}
COMMAND ${CMAKE_COMMAND} -E copy ${item} ${target}
VERBATIM
)
add_dependencies(sdk_target ${target})
endforeach()
endfunction()
This fails with an error:
CMake Error at <redacted>/build_scripts/CMakeLists.txt:209 (add_dependencies):
The dependency target
"<redacted>/sdk/CMakeLists.txt"
of target "sdk_target" does not exist.
Call Stack (most recent call first):
<redacted>/CMakeLists.txt:78 (finalize_sdk_export)
Does this not work? I WAS able to do this:
function(finalize_sdk_export destination)
file(REAL_PATH ${destination} destination )
get_property(sdk_source GLOBAL PROPERTY SDK_SOURCE )
string(REPLACE " " ";" sdk_source "${sdk_source}")
foreach (item ${sdk_source})
string(REPLACE ${destination} ${destination}/sdk target "${item}")
add_custom_command(
OUTPUT ${target}
DEPENDS ${item}
COMMAND ${CMAKE_COMMAND} -E copy ${item} ${target}
VERBATIM
)
list(APPEND sdk_files ${target})
endforeach()
add_custom_target(sdk_target ALL
COMMENT "Exporting SDK"
DEPENDS ${sdk_files}
)
endfunction()
Where I make all the custom_commands and keep a list of each ones output, then make the call to add_custom_target() with them all specified in the DEPENDS parameter.
This works for now, but I'm still just testing and I'm unsure it'll hold up if I end up having hundreds/thousands of files in the export.
So, how am I supposed to do this correctly?
(FYI, I gave up with the built in cmake install/export functionality because we really want to have control over the directory structure and look/feel of the CMake files)
All files, from which a custom target depends, should be specified in the DEPENDS option for add_custom_target() call. There is no way to add dependencies from the files afterwards.
The command add_dependencies can add only dependencies between targets.
Unlike to add_dependencies, which may connect targets creates in different directories, all generated files in DEPENDS clause should be created by add_custom_command in the same directory only. That is, it is usually not
a problem to postpone creation of the target unless all dependent files are calculated.

CMake: How can I make an IMPORTED library show up in VS

I have a CMake project that mostly uses 3 types of library
Some libraries are compiled from source
Some libraries are header only (INTERFACE)
There is one library that is IMPORTED. Which means that I provide a .lib, a .dll, and the headers.
For 1 and 2, I like that they show up in the Solution Explorer of Visual Studio.
Which I find very handy for browsing the code.
For case 3, I haven't been able to.
I would like to be able to browse the headers of this library in Visual Studio.
This is what I have tried so far:
project(steam)
if(WIN32)
if(CMAKE_SIZE_OF_VOID_P EQUAL 4)
set(STEAM_API_LIB_PATH libs/win32/steam_api.lib)
set(STEAM_API_DLL_PATH libs/win32/steam_api.dll)
else()
set(STEAM_API_LIB_PATH libs/win64/steam_api64.lib)
set(STEAM_API_DLL_PATH libs/win64/steam_api64.dll)
endif()
elseif(APPLE)
message(FATAL_ERROR "Apple not supported yet")
set(STEAM_API_LIB_PATH libs/osx/libsteam_api.dylib)
elseif(UNIX)
if(CMAKE_SIZE_OF_VOID_P EQUAL 4)
set(STEAM_API_LIB_PATH libs/linux32/libsteam_api.so)
set(STEAM_API_DLL_PATH ${STEAM_API_LIB_PATH})
else()
set(STEAM_API_LIB_PATH libs/linux64/libsteam_api.so)
set(STEAM_API_DLL_PATH ${STEAM_API_LIB_PATH})
endif()
endif()
set(SRCS
isteamapplist.h
isteamapps.h
isteamappticket.h
isteamclient.h
isteamcontroller.h
isteamdualsense.h
isteamfriends.h
isteamgamecoordinator.h
isteamgameserver.h
isteamgameserverstats.h
isteamhtmlsurface.h
isteamhttp.h
isteaminput.h
isteaminventory.h
isteammatchmaking.h
isteammusic.h
isteammusicremote.h
isteamnetworking.h
isteamnetworkingmessages.h
isteamnetworkingsockets.h
isteamnetworkingutils.h
isteamparentalsettings.h
isteamps3overlayrenderer.h
isteamremoteplay.h
isteamremotestorage.h
isteamscreenshots.h
isteamugc.h
isteamuser.h
isteamuserstats.h
isteamutils.h
isteamvideo.h
matchmakingtypes.h
steamclientpublic.h
steamencryptedappticket.h
steamhttpenums.h
steamnetworkingfakeip.h
steamnetworkingtypes.h
steamps3params.h
steamtypes.h
steamuniverse.h
steam_api.h
steam_api.json
steam_api_common.h
steam_api_flat.h
steam_api_internal.h
steam_gameserver.h
)
PREPEND(SRCS "${CMAKE_CURRENT_SOURCE_DIR}/headers/steam/" ${SRCS})
add_library(steam SHARED IMPORTED GLOBAL ${SRCS})
target_include_directories(steam INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/headers/steam)
set_target_properties(
steam
PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES
"${CMAKE_CURRENT_SOURCE_DIR}/headers"
IMPORTED_IMPLIB
"{STEAM_API_LIB_PATH}"
IMPORTED_LOCATION
"${STEAM_API_DLL_PATH}"
)
source_group("" FILES ${SRCS})

Dealing with the separator in CMake

I'm trying to compile some Java code with CMake (I'm aware that Java is not really the use-case for CMake) and I want to provide the class paths for the files. The compilation should work on both Unix and Windows systems. The problem I have is with separating the different class paths. Using:
set(CLASS_PATH ${PATH1} ${PATH2})
message(STATUS "${CLASS_PATH}")
prints
<PATH1>;<PATH2>
But this happens on both Unix and Windows. So I have to manually add separators. The way I'm doing it is
if(${CMAKE_HOST_WIN32})
set(SEP "\;")
elseif(${CMAKE_HOST_UNIX})
set(SEP ":")
endif(${CMAKE_HOST_WIN32})
Is this really the best way to deal with separators? I feel like I'm missing something.
Update - MCVE
To describe my thought: FILE_LIST would be contain all the java files that I want to compile. I defined a custom function which I can call on this FILE_LIST and compile the files. Maybe I'm doing something wrong with the function parameters?
cmake_minimum_required(VERSION 3.11)
set(CLASS_PATH E:/tmp/cmake/separator C:/tmp/)
set(FILE_LIST 1.txt 2.txt 3.txt)
add_custom_target(war ALL)
function(compile_java clp)
foreach(java_file ${ARGN})
add_custom_command(
TARGET war
PRE_BUILD
COMMAND echo "${clp}" ${java_file}
)
endforeach(java_file)
endfunction()
compile_java("${CLASS_PATH}" ${FILE_LIST}) # I have to pass CLASS_PATH in quotes
So, based on comments, you want the path list as a single command-line argument, with a platform-specific separator. You can achieve this using string operations:
function(compile_java clp)
if(NOT CMAKE_HOST_WIN32)
string(REPLACE ";" ":" clp "${clp}")
endif()
foreach(java_file ${ARGN})
add_custom_command(
TARGET war
PRE_BUILD
COMMAND echo "${clp}" ${java_file}
)
endforeach(java_file)
endfunction()

External library specific COMPILE_DEFINITIONS in cmake

I've written a cmake module for finding QCustomPlot. However, to use the shared library, one needs to #define QCUSTOMPLOT_USE_LIBRARY. I'd like to provide this define through cmake, automatically adding the definition to any project that uses QCustomPlot.
Here is a snippet of my cmake module and my current attempted solution:
SET(QCP_FOUND "NO")
IF(QCP_LIBRARY AND QCP_INCLUDE_DIR)
SET(QCP_FOUND "YES")
SET_PROPERTY(
GLOBAL
APPEND
PROPERTY COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
ENDIF(QCP_LIBRARY AND QCP_INCLUDE_DIR)
However, no linkers append the -DQCUSTOMPLOT_USE_LIBRARY flag in my compilations. What's the right way to approach this problem?
There is no global property COMPILE_DEFINITIONS. But there are such properties for directory, target and source file (see documentation). So probably the closest commands for you are:
set(QCP_FOUND "NO")
if(QCP_LIBRARY AND QCP_INCLUDE_DIR)
set(QCP_FOUND "YES")
set_directory_properties(
PROPERTIES COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
endif()
But I think that this kind of job is for imported targets:
add_library(QCP::qcp UNKNOWN IMPORTED)
set_target_properties(
QCP::qcp
PROPERTIES
IMPORTED_LOCATION "${QCP_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${QCP_INCLUDE_DIR}"
INTERFACE_COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
and usage:
add_executable(foo ...)
target_link_libraries(foo PUBLIC QCP::qcp)

Using intltool with cmake

I'm writing a GNOME application and use CMake. Now I'm considering making the app translatable, for which GNU provides intltool, gettext, msgfmt, etc.. autotools supports these tools and the entire i18n process out of the box.
How do I get this to work with CMake? Are there any modules or snippets of code around?
Nowadays, the best way to use intltool and gettext together with CMake is to, first, detect if the modules are present in the system and set a few variables like this:
# Setting up Intl
find_package (Intl REQUIRED)
find_package(Gettext REQUIRED)
include_directories(${INTL_INCLUDE_DIRS})
link_directories(${INTL_LIBRARY_DIRS})
Then, you can build the po files like this::
FIND_PROGRAM(GETTEXT_MSGFMT_EXECUTABLE msgfmt)
IF(NOT GETTEXT_MSGFMT_EXECUTABLE)
MESSAGE("------
NOTE: msgfmt not found. Translations will *not* be installed
------")
ELSE(NOT GETTEXT_MSGFMT_EXECUTABLE)
SET(catalogname rkward)
FILE(GLOB PO_FILES *.po)
SET(GMO_FILES)
FOREACH(_poFile ${PO_FILES})
GET_FILENAME_COMPONENT(_poFileName ${_poFile} NAME)
STRING(REGEX REPLACE "^${catalogname}_?" "" _langCode ${_poFileName} )
STRING(REGEX REPLACE "\\.po$" "" _langCode ${_langCode} )
IF( _langCode )
GET_FILENAME_COMPONENT(_lang ${_poFile} NAME_WE)
SET(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo)
ADD_CUSTOM_COMMAND(OUTPUT ${_gmoFile}
COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --check -o ${_gmoFile} ${_poFile}
DEPENDS ${_poFile})
INSTALL(FILES ${_gmoFile} DESTINATION ${LOCALE_INSTALL_DIR}/${_langCode}/LC_MESSAGES/ RENAME ${catalogname}.mo)
LIST(APPEND GMO_FILES ${_gmoFile})
ENDIF( _langCode )
ENDFOREACH(_poFile ${PO_FILES})
ADD_CUSTOM_TARGET(translations ALL DEPENDS ${GMO_FILES})
ENDIF(NOT GETTEXT_MSGFMT_EXECUTABLE)