arm-none-eabi-gcc cross compilation with CLion [duplicate] - linux

I'm using CLion IDE, Cmake and trying to write Hello world using CERN ROOT library.
CMakeLists.txt:
message(STATUS $ENV{ROOTSYS})
~/.bashrc:
export ROOTSYS="$HOME/tools/root-build/"
During build in CLion $ENV{ROOTSYS} is empty by some reason. But $ENV{PATH} returns correct $PATH.
What I did wrong?

Variables from .bashrc aren't passed.
Go to File -> Settings -> Build,Execution,Deployment
For Clion 2017.2+
For old Clion
Click Pass system and...
If you want to read environment variable in C++ runtime e.g. using std::getenv then
it won't work as we added environment variable for CMAKE not for runtime.
You can add such variable:
And then in your code:
std::filesystem::path getRootConfigPath()
{
// std::getenv can return nullptr and this is why we CAN'T assign it directly to std::string
const char* path = std::getenv("TEST_CONFIG_DIR");
gcpp::exception::fail_if_true(
path == nullptr, WHERE_IN_FILE, "No such environment variable: ${TEST_CONFIG_DIR}");
gcpp::exception::fail_if_true(std::string_view{path}.empty(),
WHERE_IN_FILE,
"Missing ${TEST_CONFIG_DIR} environment variable");
const std::filesystem::path testConfigDir{path};
gcpp::exception::fail_if_false(std::filesystem::exists(testConfigDir) &&
std::filesystem::is_directory(testConfigDir),
WHERE_IN_FILE,
"Invalid ${TEST_CONFIG_DIR} dir:" + testConfigDir.string());
return testConfigDir;
}
Source of gcpp::exception::fail_if_true
Other way to do this in more friendly way when running unit tests is add this variable to template.
So whenever you click:
Such variable will be there already.

From CLion developers FAQ:
Q: How to pass environment variables and parameters to CMake in CLion?
A: The best way is to use Preferences/Settings | Build, Execution, Deployment | CMake dialog.
As for .bashrc file, it is only used by bash. CLion doesn't need to use bash for run configuration process.

On Ubuntu 17.04, you can set a permanent environment variable by modifying
/etc/enviornment
[I assume you can do this in other versions of Linux, but I provide the version of the system that I am using.]
For example, I am compiling test cases that assume that ${GOOGLE_MOCK} has been set. I added the following to my /etc/environment file, and now I don't have to rewrite all of my CMakeLists.txt files:
GOOGLE_MOCK=/usr/local/src/googletest/googlemock
GOOGLE_TEST_HOME=/usr/local/src/googletest/googletest
Clion just became much more useable.

One thing you can check is the .gdbinit. Clion on Linux will invoke the gdb, which will read in the .gdbinit. I happen to have set environment LD_LIBRARY_PATH xxx in my .gdbinit file, which will override whatever you set LD_LIBRARY_PATH from shell, whether through direct export or through .bashrc, or from CLion environment variable panel.
Hope this helps.

Source your variables in .profile not .bashrc

Related

Environment variable not found by cmake

I'm working on Ubuntu 14.04 with ROS Indigo and I need to use Geometry Tools Wild Magic 5 for developing a package.
I have exported the path to Wild Magic folder as an environment variable by modifying .bashrc as follows:
export WM5_PATH=/home/user/catkin_ws/src/GeometricTools/WildMagic5/SDK
This is done to specify locations of header files in the CMakeLists.txt file of the package I'm coding:
include_directories(
include
$ENV{WM5_PATH}/Include/
)
Previously, in the same cmake file I check if the environmental variable is correctly set:
if (NOT DEFINED ENV{WM5_PATH})
MESSAGE (FATAL_ERROR "Wild Magic Engine 5.14 missing")
endif()
Now, while building the package using catkin build the environment variable is not found (the if above is entered). But by using printenv in the terminal I can see that the environment variable WM5_PATH is actually there.
How could I solve this problem?
I've just given your example a try and it works fine in my Ubuntu bash shell.
# export WM5_PATH=/home/user/catkin_ws/src/GeometricTools/WildMagic5/SDK
# cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: ...
So I suspect your cmake executable runs in another environment (e.g. an IDE).
To check what your CMake does see as an environment you could add the following to your CMakeLists.txt:
execute_process(
COMMAND ${CMAKE_COMMAND} -E environment
)
Reference
How to retrieve a user environment variable in CMake (Windows)

How to manage the environment PATH used by the Android NDK build?

I use swig from my within Android.mk. I reference it directly relying on the $PATH variable to contain the path to it's executable.
The issue is that the $PATH variable is different depending on where the android-ndk tool is run from.
Background
In my Android.mk file:
# some stuff ...
#echo "$(PATH)"
swig # swig parameters here...
# more stuff ...
From the terminal, we see the system path includes the path to swig:
which swig
/usr/local/bin/swig
echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:
Issue
When the android-ndk is run from within Android Studio I get the following for PATH (note: it's missing the swig path):
/usr/bin:/bin:/usr/sbin:/sbin
This causes my build to fail because "swig" isn't recognised:
make: swig: Command not found
However, if I run the android-ndk directly from the terminal, then the PATH used is the same as my system path and the build works fine:
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:
Bad solution
Yes, I could add the path manually to my Android.mk file:
export PATH:=/usr/local/bin/:$(PATH)
However, I'd prefer not to define specific paths for my machine knowing that the whole team uses this file.
Question
I'd prefer the Android.mk file to use my systems PATH instead.
Any ideas how to do this?
Thanks!
The thing in my opinion is that environment variables may be different whether the process is launched from terminal or from the GUI (launchpad, spotlight, ...).
The former would use PATH as set in bashrc (or other shell related startup files) while the other will not.
I think you might find interesting information on how to change the environment variables for the launch deamon in the following question:
Setting environment variables in OS X?

qmake and system variables - Linux vs. Windows

This is a follow up to this previous question of mine.
Here is the (simplified) location in that qmake script that causes problems (I'm currently testing only this particular library but I've also checked and the same issue is present with the others too):
VTK_API = ""
CONFIG(debug, debug|release) {
message(Application will be built in DEBUG mode)
VTK_API = $$(VTK_DBG_DIR)
}
else {
message(Application will be built in RELEASE mode)
VTK_API = $$(VTK_DIR)
}
I've moved my qmake project file to Linux to check how it's working there. And for my surprise the environment variables are not read properly that is when I output the value from the given variable it's empty. I've adjusted the paths for both versions of the library since I have a different naming of the respective environment variables (in .bashrc) that point at the location of its debug and release builds.
user#debian:~$ echo $VTK_DBG_DIR
/opt/vtk-dbg/lib
user#debian:~$ echo $VTK_DIR
/opt/vtk/lib
As you can see the variables are properly echoed in my terminal. I also have to add that I start my Qt Creator from my bash terminal due to some other things that I want loaded along with the IDE so the case "Your variables are not read since Qt Creator doesn't read what's in your .bashrc" is not present here.
Any idea what's going on here? Is there a difference in the way the loading of environment variables works in qmake based on the operating system or am I missing something else here (an error in my script perhaps)?

Set linker search path for build in CMake

It seems this question has been asked very often before but none of the solutions seem to apply in my case.
I'm in a CMake/Linux environment and have to run an executable binary during the build step (protoc in particular).
This binary needs a library but it's not installed (and cannot be) in the in the standard directories like /usr, so the library cannot be found.
Unfortunately I cannot manipulate the protoc call because it's embedded in a 3rd party script.
I can now set LD_LIBRARY_PATH before every make or set it system wide but this is very inconvenient especially when it comes to IDEs in which the build takes place or distributed build scenarios with continuous build environments.
I tried to set LD_LIBRARY_PATH via
set(ENV{LD_LIBRARY_PATH} "/path/to/library/dir")
but this seems to have no effect during the build step.
So my question is: can I set a library search path in CMake which is used during the build?
Try this
SET(ENV{LD_LIBRARY_PATH} "/path/to/library/dir:$ENV{LD_LIBRARY_PATH}")
I also used this dirty trick to temporary change some environment variables:
LD_LIBRARY_PATH="/path/to/library/dir:$LD_LIBRARY_PATH" cmake ...
After execution of this line LD_LIBRARY_PATH is not changed in the current shell.
Also, I do not find it bad to change LD_LIBRARY_PATH before invoking cmake:
export LD_LIBRARY_PATH=...
It won't change anything system-wide, but it would be used for your current shell, current build process. The same holds for CI builds. You can save the variable and restore it after cmake invocation:
MY_LD=$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=...
cmake...
export LD_LIBRARY_PATH=$MY_LD
I have recently run into a somewhat similar problem.
My solution was to incorporate sourcing a file that set the appropriate environment into every command.
For example, this custom command:
add_custom_command(
OUTPUT some_output
COMMAND some_command
ARGS some_args
DEPENDS some_dependencies
COMMENT "Running some_command some_args to produce some_output"
)
Would become:
set(my_some_command_with_environment "source my_environment_script.sh && some_command")
add_custom_command(
OUTPUT some_output
COMMAND bash
ARGS -c "${my_some_command_with_environment} some_args"
DEPENDS some_dependencies
COMMENT "Running some_command some_args to produce some_output"
VERBATIM
)
Obviously, this has some disadvantages:
It relies on a bash shell being available.
It sources the environment script for every command invocation (performance issue) and you will have to change all invocations of commands that rely on that environment variables.
It changes the normal syntax of having the command follow COMMAND and the arguments follow ARGS, as now the 'real' command is part of the ARGS.
My CMake-Fu has proven insufficient to find a syntactically nicer way of doing this, but maybe somebody can comment a nicer way.
I had a similar issue for an executable provided by a third party library. The binary was linked against a library not provided by the distribution but the required library was included in the libs directory of the third party library.
So running LD_LIBRARY_PATH=/path/to/thirdparty/lib /path/to/thirdparty/bin/executable worked. But the package config script didn't set up the executable to search /path/to/thirdparty/lib for the runtime dependent so CMake would complain when CMake tried to run the executable.
I got around this by configuring a bootstrap script and replacing the IMPORTED_LOCATION property with the configured bootstrapping script.
_thirdpartyExe.in
#!/bin/bash
LD_LIBRARY_PATH=#_thirdpartyLibs# #_thirdpartyExe_LOCATION# "$#"
CMakeLists.txt
find_package(ThirdPartyLib)
get_target_property(_component ThirdPartyLib::component LOCATION)
get_filename_component(_thirdpartyLibs ${_component} DIRECTORY)
get_target_property(_thirdpartyExe_LOCATION ThirdPartyLib::exe IMPORTED_LOCATION)
configure_file(
${CMAKE_CURRENT_LIST_DIR} _thirdpartyExe.in
${CMAKE_BINARY_DIR}/thirdpartyExeWrapper #ONLY
)
set_target_properties(ThirdPartyLib::exe PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/thirdpartyExeWrapper)
Honestly I view this as a hack and temporary stop gap until I fix the third party library itself. But as far as I've tried this seems to work on all the IDE's I've thrown at it, Eclipse, VSCode, Ninja, QtCreator, ... etc

cmake : Set environment variables from a script

I have a script that sets all variables needed for the cross-compilation. Here is just part of it :
export CONFIG_SITE=~/workspace/eldk-5.4/powerpc/site-config-powerpc-linux
export CC="powerpc-linux-gcc -m32 -mhard-float --sysroot=~/workspace/eldk-5.4/powerpc/sysroots/powerpc-linux"
export CXX="powerpc-linux-g++ -m32 -mhard-float --sysroot=~/workspace/eldk-5.4/powerpc/sysroots/powerpc-linux"
export CPP="powerpc-linux-gcc -E -m32 -mhard-float --sysroot=~/workspace/eldk-5.4/powerpc/sysroots/powerpc-linux"
export AS="powerpc-linux-as "
export LD="powerpc-linux-ld --sysroot=~/workspace/eldk-5.4/powerpc/sysroots/powerpc-linux"
export GDB=powerpc-linux-gdb
If I do source environment-setup-powerpc-linux, all environment variables are imported into the current shell session, and I can compile my example.
Is it possible to import these variables in cmake? If yes, how?
A bit more details :
I am using ELDK v 5.4, and it's install script generates a script which sets all environment variables
I found this tutorial, which explains how to manually set for cross-compilation, but not how to use the script, which sets everything
if I call the script before setting cmake, all works fine, and I can cross-compile, but I'd like that cmake calls the script
Reading through the cmake quick start, you can specify variable on a command line:
cmake -DVARIABLE1=value1 -DVARIABLE2=value2 ...
Otherwise, set command in the cmake script is probably what you want, see the reference manual. To set the environment variable PATH, do:
set(ENV{PATH} "/home/martink")
To set normal variable, do:
set(variable "value")
Not sure which ones you have to set, probably the environment ones.
That said, setting environment variable prior to calling cmake is often the easiest solution to solve the problem. If you want a cross-platform way to do this that doesn't depend on the syntax of a specific shell to set environment variables, there is the cmake -E env command.
The only way to set a compiler and flags to do cross-compilation reliably with CMake is with a toolchain-file as done in the tutorial you have found.
When we faced the same issue you have (a toolkit which produces a script so set the compile-environment) we changed the toolkit in a way that it produces a toolchain-file along with the script.
In reality a cmake-toolchain-file does not change that often. The basic flags used for the target are fixed quite early in a project - normally. And with CMake's CMAKE_BUILD_TYPE you can switch between Debug and Release compilations without changing the toolchain-file.
If you have different targets to support, create different toolchain and use the out-of-source-build with CMake.
EDIT: One thing you could do is to invoke cmake with the -D-argument setting the variables you want to and having sourced your script before:
source environment-setup-powerpc-linux
cmake -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX etc
The result will be identical as to having used a toolchain-file.

Resources