How to make a project written with Tcl in CMake? - cmake

I am using cmake version 3.14.0-rc3 to make my codes. When I target any code written in C or C++ in my CMakelist.txt as follows, it works pretty and makes the executable file.
cmake_minimum_required(VERSION 3.3)
PROJECT (HELLO)
ADD_EXECUTABLE(hello hello_world.cpp)
but while I am trying to make this code with Tcl scripts, it fails and I receive the following fatal error:
Fatal error while making a tcl script with cmake
Can anyone help me to overcome this issue? It seems that cmake is not normally able to compile Tcl scripts.
Thank in advance for your kind replies and helps.
Bests,
Daryon

You have to watch out for a different path, e.g., running custom commands or adding custom targets to your CMake project. You seem to confuse the nature of libraries, executables, and external commands in the context of CMake, I am afraid.
I think there should be a way to execute Tcl scripts with CMake as
well.
You might want to attempt the following: In CMakeLists.txt, you define a custom target MyTarget that calls out to a TCLSH executable, if available:
CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
PROJECT (HELLO)
find_program (TCLSH tclsh)
if (TCLSH)
add_custom_target(
MyTarget ALL
COMMAND TCLSH myScript.tcl
)
endif (TCLSH)
(1) find_program and if/endif will make the custom target only available under the condition that an executable called tclsh was found.
(2) myScript.tcl is a Tcl script in your project directory.
(3) Running cmake . && make will call out to effectively to: tclsh myScript.tcl, producing:
$cmake . && make
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/hello
This is a message written by Tcl scripts
Built target MyTarget
This is just to get you started, you will have to read more about adding commands, targets, or executing sub-processes from within CMake.

Related

CMake to reload CMakeLists.txt during build

The short version
during a compilation with CMake, a tool can modify (only once) the CMakeLists.txt file. If this happens, I would like to be able to restart the compilation from the beginning (rereading of dependencies, compilation flags, ... Is this possible? (and how to do it :) ?
The long version
My application deals with an RTOS for embedded systems. I have one file (.oil) that describes the application (tasks properties, sync…) and several C/C++ source files (OS, drivers, app). The system is built in 2 steps:
a dedicated compiler (goil) generates the data structures of the applications (.c/.h/.s)
gcc compiles all the stuff and ld links
The .oil file also embeds some compilation rules (flags, ...) and the compiler (goil) generates a build script in Python. The first time, we call goil directly (bootstrap), and then the python script calls goil if the .oil file has been updated.
I would like to switch to CMake. The problem is:
I first call goil that generates the CMakeLists.txt (bootstrap). Ok
then Cmake will call goil again if the .oil is updated and will generate the binary. Ok
but goil can also update the compilation rules and generate again the CMakeLists.txt. In this case, the compilation follows, with the old configuration, and I have to build twice to have the correct behavior. Is it possible to force CMake to restart from the beginning at some point? Here is my cmake rule (that calls goil):
#goil
add_custom_command(OUTPUT ${APP_GENERATED_SRS}
DEPENDS ${OILFILE}
COMMAND ${OILCOMPILER} ${OILFLAGS} ${OILFILE}
#Here if CMakeLists.txt has been updates, I would like to restart…
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "call Goil (.oil to code source)"
)
regards

CMake call add_subdirectory within custom command

I'm working with a code generator that produces C++ and a CMakeLists.txt file, unfortunately I cannot use this in my main CMakeLists.txt file for testing purposes.
For example you have the following CMakeLists.txt file:
project(SomeProject CXX C)
add_custom_command(OUTPUT ${SRCS}
COMMAND ${CODEGEN_CLI_PATH} -i "${INPUT}" -o "${OUT}"
COMMENT "Generating sources"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM
)
add_custom_target(CODEGEN
DEPENDS
${SRCS}
)
# Needs to be executed after the custom command
add_subdirectory(${GENERATED_CMAKE_LISTS_LOCATION})
Is it possible to use functions such as add_subdirectory only after you execute custom commands for a particular target, such as CODEGEN?
I've already tried to execute it by adding an extra line to the existing custom command:
COMMAND ${CMAKE_COMMAND} -D DIR=${GENERATED_CMAKE_LISTS_LOCATION} -P add_subdirectories.cmake
Unfortuantly this doesn't work because it isn't allowed to execute functions like add_subdirectory in script mode.
Neither I can manage to call custom made functions (that are executing add_subdirectory) from add_custom_command that are located in the same file.
Nope, it is not possible. The add_subdirectory command is run during configuration step, while CODEGEN is a target that runs during build.
You seem to be doing something wrong, so the only advice I can give you is to use execute_process command to run commands you need. The execute_process command is executed during configuration stage, so it will be able to generate files you need before add_subdirectory.
But again, please describe your problem, why do you want CMake to do that.
I have a huge fixed unsigned char array that I compiled into a static library. The way I work around it is by:
if(NOT EXISTS ${PATH_TO_FOLDER}/smeagol.a)
add_subdirectory(smeagol)
endif()
I'm still looking for a nicer kung-fu way to do it using cmake. I feel that its out there, and I will update this answer once i find it.

cmake try_compile: Using library found in configure

I am building a project with cmake. The project uses the external library plplot; I have configured cmake to the library and headers, and that is cached in variables ${PLPLOT_LIBRARY}, ${PLPLOT_LIB_PATH} and ${PLPLOT_INCLUDE_PATH}. In the plplot library a function has changed name: plwid -> plwidth and I want to detect that. I have written a small try_compile() test:
try_compile(HAVE_PLWID ${CMAKE_BINARY_DIR} cmake/tests/test_plwid.c)
However this test will always fail, because I have to pass header and library information to the try_compile process. Invoking gcc manually like this:
gcc -I${PLPLOT_INCLUDE_PATH} cmake/tests/test_plwid.c -L${PLPLOT_LIB_PATH} -l${PLPLOT_LIBRARY}
works. However I don understand how to pass the necessary flags to the try_compilecommand: I have tried:
try_compile(HAVE_PLWID ${CMAKE_BINARY_DIR} cmake/tests/test_plwid.c
INCLUDE_DIRECTORIES ${PLPLOT_INCLUDE_PATH}
LINK_DIRECTORIES ${PLPLOT_LIB_PATH}
LINK_LIBRARIES ${PLPLOT_LIBRARY})
Then I just get the cmake configure error:
Attempt at a recursive or nested TRY_COMPILE in directory
/path/to/build
I am quite confident the ${PLPLOT_XXX} variables are correct, at least the rest of the build works fine based on these variables.
Update: If I invoke cmakewith the --debug_trycompile command and go to the build/CMakeFiles/CMakeTmp directory and invoke cmakethere manually as:
cmake . -DINCLUDE_DIRECTORIES=/path/plplot/include -DLINK_DIRECTORIES=/path/to/plplot/lib -DLINK_LIBRARIES=plplotd
The test program will build and link correctly; so it seems the challenge is to pass these options correctly to the try_compile() cmake command invocation?
The LINK_DIRECTORIES and INCLUDE_DIRECTORIES cannot be passed as options to try_compile but have to passed as extra flags with the CMAKE_FLAGS option in the following way:
try_compile(HAVE_PLWID "${CMAKE_BINARY_DIR}/temp" "${CMAKE_SOURCE_DIR}/tests/test_plwid.c"
LINK_LIBRARIES ${PLPLOT_LIBRARY}
CMAKE_FLAGS
"-DINCLUDE_DIRECTORIES=${PLPLOT_INCLUDE_PATH}"
"-DLINK_DIRECTORIES=${PLPLOT_LIB_PATH}")

CMake build & link to library without installing to /usr/local or elsewhere

I'm trying to include an external library in a build environment that uses CMake. I'm not trying to install it on the local system (in fact I'd rather not do that, I don't want /usr/local clogged up with all kinds of libraries); I'd just like to have the resulting libxml2.a available for linking with my executable. I can build it fine with the following in CMakeLists.txt:
set (LIBXML_PATH ${MY_SOURCE_DIR}/libxml2-2.9.1)
add_custom_target (build_libxml ALL
COMMENT "Building libxml"
COMMAND ./configure --prefix=/tmp
COMMAND make
WORKING_DIRECTORY ${LIBXML_PATH}
)
But I'm still having trouble with the following:
1) Is this the right approach in the first place, for the general purpose of getting libraries built with configure and make into a CMake environment?
2) How do I get the resulting library (i.e. libxml2.a) under my build output directory?
3) How can I link to that library for my executable builds?
I tried a fiddly solution with
ADD_LIBRARY( xml2 STATIC libxml2.a )
but it seems like there must be a better way than hauling a whole library's contents into… a library.
Thanks.
You need to make it clearer to CMake what is going on here. All it can see now is that you have some custom command that it will run every time. Instead of using add_custom_target with COMMAND, I've found it better to use add_custom_command.
Something like this:
set (LIBXML_PATH ${MY_SOURCE_DIR}/libxml2-2.9.1)
add_custom_command(
OUTPUT libxml2.a
COMMENT "Building libxml"
COMMAND ./configure --prefix=/tmp
COMMAND make
WORKING_DIRECTORY ${LIBXML_PATH}
)
target_link_libraries(your-program libxml2.a)
By doing it this way, CMake can understand that your custom command's essential product is libxml2.a, and when CMake sees something depending on that, it will run the command (if the library doesn't exist already).

Run Command after generation step in CMake

I have a command line tool that should be run after CMake created my .sln-file. Is there any way to do that using CMake?
Using execute_process(COMMAND ..) at the end of the CMakeLists.txt does not help because this is executed after the Configure step, however, the .sln-file is created in the generation step.
Thanks a lot!
A rather horrifying way to do it is by calling cmake from cmake and doing the post-generate stuff on the way out of the parent script.
option(RECURSIVE_GENERATE "Recursive call to cmake" OFF)
if(NOT RECURSIVE_GENERATE)
message(STATUS "Recursive generate started")
execute_process(COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-T "${CMAKE_GENERATOR_TOOLSET}"
-A "${CMAKE_GENERATOR_PLATFORM}"
-DRECURSIVE_GENERATE:BOOL=ON
${CMAKE_SOURCE_DIR})
message(STATUS "Recursive generate done")
# your post-generate steps here
# exit without doing anything else, since it already happened
return()
endif()
# The rest of the script is only processed by the executed cmake, as it
# sees RECURSIVE_GENERATE true
# all your normal configuration, targets, etc go here
This method doesn't work well if you need to invoke cmake with various combinations of command line options like "-DTHIS -DTHAT", but is probably acceptable for many projects. It works fine with the persistently cached variables, including all the cmake compiler detection when they're initially generated.
From the following links, it seems like there is no such command to specify execution after CMake generated .sln files.
https://cmake.org/pipermail/cmake/2010-May/037128.html
https://cmake.org/pipermail/cmake/2013-April/054317.html
https://cmake.org/Bug/view.php?id=15725
An alternative is to write a wrapper script as described in one of the above links.
cmake ..
DoWhatYouWant.exe
Yes, add_custom_command paired with add_custom_target got this covered
http://cmake.org/cmake/help/cmake-2-8-docs.html#command:add_custom_command
http://cmake.org/cmake/help/cmake-2-8-docs.html#command:add_custom_target
For an example take a look at my answer to another question
cmake add_custom_command